A common idiom

I often have to write something like

some_enumerator.collect … # or collect.with_index …

next if …

end.reject(&:nil?)

Is there a better way to do a “collect_unless_nil”, avoiding the double
processing ?
_md

On Fri, Dec 31, 2010 at 7:12 PM, Michel D. [email protected]
wrote:

_md
For one, you can use #compact instead of #reject.
The way I’d do it is:

results = []
some.each do |value|
results << value.operation if value.condition?
end

And then you could also use inject, which is a bit harder to grasp at
a glance and a bit more wordy, but some people believe you should
avoid variables outside of blocks at all costs… even if you end up
assigning the results to one.

some.inject [] do |results, value|
next results unless value.condition?
results << value.operation
end

Also, at least since 1.9, you can use some.each_with_index or
some.to_enum.with_index.inject.

Michael F. wrote in post #971622:

compact
Yes ! I knew there was a method, but forgot the name, browsed thru
Flanagan-Matz, and did not find it.

results = []
some.each do |value|
results << value.operation if value.condition?
end

Yes, returning results, but I try to avoid this extra variable. I
dislike (question of taste) the pattern
def …
res = []

res <<

res
end

Another way is using tap

Array.new.tap do |res|

end

A bit snob, no ?

On Dec 31, 2010, at 02:12 , Michel D. wrote:

I often have to write something like

some_enumerator.collect … # or collect.with_index …

next if …

end.reject(&:nil?)

Is there a better way to do a “collect_unless_nil”, avoiding the double
processing ?

compact:

result = collection.map { |x|
next if x.hinkey?
}.compact

that will be a LOT faster than your second pass with reject/nil?.

Ryan D. wrote in post #971625:

}.compact

that will be a LOT faster than your second pass with reject/nil?.
Yes, that’s what I was looking for (could not remember/guess the name).
Thks

enumerator.each_with_object [] do |value, memo|
memo << value if value.nil?
end

enumerator.each_with_object [] do |value, memo|
memo << value unless value.nil?
end

A benchmark for the five variants
user system total real
[] 3.235000 0.047000 3.282000 ( 3.296875)
tap 3.265000 0.000000 3.265000 ( 3.265625)
compact 3.547000 0.016000 3.563000 ( 3.562500)
reject 5.078000 0.015000 5.093000 ( 5.093750)
memo 9.610000 0.000000 9.610000 ( 9.609375)

_md