ruby 多行与内嵌块之间的不同行为

wkyowqbh  于 2023-01-12  发布在  Ruby
关注(0)|答案(1)|浏览(165)

我很好奇为什么这些会产生不同的输出。所需的输出是一个ActiveRecord记录数组。
使用内嵌块时,它看起来像是在执行ActiveRecord查找,但随后将原始数组(减去reject ed元素)嵌套在另一个数组中,并将嵌套的数组追加到变量。
使用多行块时,会发生预期的行为,即,发生ActiveRecord查找,并将标识的记录追加到变量中。

x = []
y = ["", "1353", "1155"]
x << y.reject!(&:empty?).each { |i| User.find(i) }
# => ["1353", "1155"]
x
#=> [["1353", "1155"]]

对比

x = []
y = ["", "1353", "1155"]
y.reject!(&:empty?)
y.each do |i|
  x << User.find(i)  
end  
# => ["1353", "1155"]
x
#=> [#<User:0x00007fc7fbacc928
#  id: 1353,
#  login: nil,
...
agxfikkp

agxfikkp1#

不同之处在于.each返回数组本身,因此

[1,2,3].each { nil }
# [1,2,3]

所以你要把被拒绝的Y数字追加到X中,而你的.each在第一个例子中是无用的(这也是为什么它是一个数组的数组,因为'〈〈'在数组中插入元素数组,而不是所有的单个元素)
在你的第二个例子中,你的“each”实际上是把元素追加到块内的数组中,所以没有“return”依赖。如果你想在一行中完成,你必须

y.reject(&:empty?).each { |i| x << User.find(i) }

所以它会在de块内部进行计算,如果你想让每个循环都返回块内部的值,你应该使用'map'而不是'each',并使用'concat'或'+'来对数组求和(所以它对每个单独的元素求和或进行concat),所以

x.concat(y.reject(&:empty?).map{ |i| User.find(i) })

OBS:正如@tadman在评论中建议的那样,我也删除了reject的“刘海”,因为'reject!'方法并不总是返回所有的值,查看他的评论以获得更多信息

相关问题