method

flat_map

Importance_4
Ruby latest stable (v2_5_5) - 5 notes - Class: Enumerable
flat_map() public

Returns a new array with the concatenated results of running block once for every element in enum.

If no block is given, an enumerator is returned instead.

[1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
[[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
Show source
Register or log in to add new notes.
November 16, 2011
1 thank

Alternative definition

a.flat_map(&b) works exactly like a.map(&b).flatten!(1).

November 3, 2015
1 thank

Re: close but no bananna

Actually, @tarasevich is right on this. Let’s have a look at your own example:

[["1","2"],["3","4"]].flat_map {|i| i[0] }     # => ["1", "3"]

[["1","2"],["3","4"]].map {|i| i[0] }.flatten  # => ["1", "3"]
[["1","2"],["3","4"]].flatten.map {|i| i[0] }  # => ["1", "2", "3", "4"]

You are right that both #map and #flatten are non-commutative, it does matter which method is called first.

But #flat_map is equivalent to mapping first and then concatenating (flatten) the results, even if the name might suggest the opposite.

To correctly interpret the method name, you should think of it mathematically as a function composition.

March 1, 2015
0 thanks

Not exactly like map {}.flatten

To clarify on the last comment, conceptually it’s the same, but #flat_map will perform better because there is no need to create an intermediate Array

May 22, 2015 - (>= v1_8_6_287)
0 thanks

Not exactly like map {}.flatten

To also give dimension, is about 4.5 times faster then map {}.flatten.

November 3, 2015 - (>= v1_9_2_180)
0 thanks

close but no bananna

@tarasevich noted that

a.flat_map(&b) works exactly like a.map(&b).flatten!(1)

This is backwards because map and flatten are not always interchangeable in order. Mapping over the example array only gives you 2 items. This can result in significant differences depending on what you’re doing in the map. This is easier to demonstrate if we change the example to strings.

[["1","2"],["3","4"]].map {|i| i[0] } # => ["1", "3"]
[["1","2"],["3","4"]].map {|i| i[0] }.flatten  # => ["1", "3"]

BUT if you swap the order

[["1","2"],["3","4"]].flatten.map {|i| i[0] } # => ["1", "2", "3", "4"]

in order to remember what it is equivalent to just note that the method name is already in the correct order. flat_map -> flatten + map