In Ruby, is there an Array method that combines 'select' and 'map'?

Viewed 73226

I have a Ruby array containing some string values. I need to:

  1. Find all elements that match some predicate
  2. Run the matching elements through a transformation
  3. Return the results as an array

Right now my solution looks like this:

def example
  matchingLines = @lines.select{ |line| ... }
  results = matchingLines.map{ |line| ... }
  return results.uniq.sort
end

Is there an Array or Enumerable method that combines select and map into a single logical statement?

14 Answers

Ruby 2.7+

There is now!

Ruby 2.7 is introducing filter_map for this exact purpose. It's idiomatic and performant, and I'd expect it to become the norm very soon.

For example:

numbers = [1, 2, 5, 8, 10, 13]
enum.filter_map { |i| i * 2 if i.even? }
# => [4, 16, 20]

Here's a good read on the subject.

Hope that's useful to someone!

If you want to not create two different arrays, you can use compact! but be careful about it.

array = [1,1,1,2,3,4]
new_array = map{|n| n*3 if n==1}
new_array.compact!

Interestingly, compact! does an in place removal of nil. The return value of compact! is the same array if there were changes but nil if there were no nils.

array = [1,1,1,2,3,4]
new_array = map{|n| n*3 if n==1}.tap { |array| array.compact! }

Would be a one liner.

Related