Skip iteration in Enumerable # collect

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

If the condition for next met, collect puts nil in the array, whereas what I'm trying to do does not put the element in the returned array if the condition is met. Is this possible without calling delete_if { |x| x == nil } delete_if { |x| x == nil } in the returned array?

(Using Ruby 1.8.7, my code snippet is very abstracted)

+51
ruby enumerable
Mar 01 2018-11-11T00:
source share
5 answers

There is an Enumerable#reject method that serves this purpose only:

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

The practice of directly using the output of one method as the input of another is called the method chain and is very common in Ruby.

BTW, map (or collect ) is used to directly display the input enumerated on the output. If you need to output a different number of elements, perhaps you need a different Enumerable method.

Edit: If you are concerned about the fact that some of the elements are repeated twice, you can use a less elegant inject based inject (or its similar method called each_with_object ):

 (1..4).each_with_object([]){|x,a| a << x + 1 unless x == 3} 
+73
Mar 01 '11 at 9:11
source share

I would just call .compact in the resulting array, which removes all nil instances in the array. If you want to modify an existing array (for no reason), use .compact! :

 (1..4).collect do |x| next if x == 3 x end.compact! 
+43
Mar 01 2018-11-11T00:
source share

just a suggestion why don't you do this:

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

this way you saved another iteration to remove nil elements from the array. hope this helps =)

+4
Mar 01 2018-11-11T00:
source share

I suggest using:

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

instead of the collect + next command.

0
Mar 01 2018-11-11T00:
source share

You can output the decision to a helper method and use it through 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] 
0
Jun 15 '14 at 5:52
source share



All Articles