跳过Enumerable#collect中的迭代

(1..4).collect do |x| next if x == 3 x + 1 end # => [2, 3, nil, 5] # desired => [2, 3, 5] 

如果下next条件满足, collect放在数组中的nil ,而我想要做的是没有元素在返回的数组,如果条件满足。 这可能没有调用delete_if { |x| x == nil } delete_if { |x| x == nil }在返回的数组?

(使用Ruby 1.8.7;我的代码摘要很抽象)

有方法Enumerable#reject服务的目的:

 (1..4).reject{|x| x == 3}.collect{|x| x + 1} 

直接使用一个方法的输出作为另一个方法的input的做法称为方法链接 ,在Ruby中非常常见。

顺便说一句, map (或collect )用于input枚举到输出的直接映射。 如果你需要输出不同数量的元素,那么你可能需要另一种Enumerable方法。

编辑:如果您对某些元素迭代了两次这一事实感到困扰,那么可以使用基于inject (或其类似方法,名为each_with_object )的较不优雅的解决scheme:

 (1..4).each_with_object([]){|x,a| a << x + 1 unless x == 3} 

我只是简单地调用结果数组上的.compact ,它将删除数组中的所有nil实例。 如果你想修改现有的数组(没有理由不),可以使用.compact!

 (1..4).collect do |x| next if x == 3 x end.compact! 

只是一个build议,你为什么不这样做:

 result = [] (1..4).each do |x| next if x == 3 result << x end result # => [1, 2, 4] 

这样你保存了另一个迭代来从数组中删除nil元素。 希望它有助于=)

我会build议使用:

 (1..4).to_a.delete_if {|x| x == 3} 

而不是collect + next语句。

您可以将决策制定为辅助方法,并通过Enumerable#reduce使用它:

 def potentially_keep(list, i) if i === 3 list else list.push i end end # => :potentially_keep (1..4).reduce([]) { |memo, i| potentially_keep(memo, i) } # => [1, 2, 4]