Enumerable#flat_map

Returns: Array · Added in v1.8.7 · Updated March 16, 2026 · Enumerable
ruby enumerable transformation flatten

The flat_map method transforms each element with a block and then flattens the result by one level. It’s equivalent to calling map followed by flatten(1), but more efficient and readable.

How It Works

flat_map combines two operations:

  1. Map — transform each element with a block
  2. Flatten — merge the resulting arrays into one
collection.flat_map { |element| block_return }
# Equivalent to: collection.map { ... }.flatten(1)

Basic Usage

Flatten an array of arrays:

numbers = [[1, 2], [3, 4], [5, 6]]
result = numbers.flat_map { |arr| arr }
# => [1, 2, 3, 4, 5, 6]

Transform and flatten in one step:

words = ["hello", "world"]
result = words.flat_map { |word| word.chars }
# => ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]

Extracting Nested Data

Extract all phone numbers from a collection of users:

users = [
  { name: "Alice", phones: ["home: 555-1234", "work: 555-5678"] },
  { name: "Bob", phones: ["mobile: 555-9012"] },
  { name: "Carol", phones: ["home: 555-3456", "work: 555-7890", "mobile: 555-1122"] }
]

all_phones = users.flat_map { |user| user[:phones] }
# => ["home: 555-1234", "work: 555-5678", "mobile: 555-9012", "home: 555-3456", "work: 555-7890", "mobile: 555-1122"]

Splitting Strings

Break sentences into words:

sentences = [
  "Hello world",
  "How are you",
  "Goodbye friend"
]

words = sentences.flat_map { |sentence| sentence.split }
# => ["Hello", "world", "How", "are", "you", "Goodbye", "friend"]

With Conditional Logic

Generate multiple results per element:

numbers = [1, 2, 3, 4, 5]

# Return just the number if even, nothing if odd
result = numbers.flat_map { |n| n.even? ? [n] : [] }
# => [2, 4]

# Return the number and its double if odd
result = numbers.flat_map { |n| n.odd? ? [n, n * 2] : [] }
# => [1, 2, 3, 6, 5, 10]

Transforming Hashes

Convert an array of hashes into key-value pairs:

configs = [
  { name: "debug", value: true },
  { name: "timeout", value: 30 }
]

pairs = configs.flat_map { |h| h.to_a }
# => [[:name, "debug"], [:value, true], [:name, "timeout"], [:value, 30]]

Practical Examples

Reading Multiple Files

filenames = ["a.txt", "b.txt", "c.txt"]

# Read each file and split into lines
all_lines = filenames.flat_map { |filename| 
  File.read(filename).split("\n") 
}

Generating Permutations

[1, 2, 3].flat_map { |n| [n, -n] }
# => [1, -1, 2, -2, 3, -3]

# Cartesian product
sizes = ["S", "M", "L"]
colors = ["red", "blue"]

options = sizes.flat_map { |size| colors.map { |color| "#{size}-#{color}" } }
# => ["S-red", "S-blue", "M-red", "M-blue", "L-red", "L-blue"]

Building a List of Dependencies

projects = [
  { name: "web", deps: ["rails", "redis"] },
  { name: "api", deps: ["rails", "jwt"] },
  { name: "worker", deps: ["redis"] }
]

all_deps = projects.flat_map { |p| p[:deps] }.uniq
# => ["rails", "redis", "jwt"]
MethodWhat It Does
mapTransforms each element, returns array of arrays if block returns arrays
flattenMerges nested arrays into one, but doesn’t transform
flat_mapTransforms AND flattens in one pass
collectAlias for map
numbers = [[1, 2], [3, 4]]

numbers.map { |x| x }        # => [[1, 2], [3, 4]]
numbers.flatten              # => [1, 2, 3, 4]
numbers.flat_map { |x| x }   # => [1, 2, 3, 4]

Performance Notes

  • flat_map is more efficient than map.flatten(1) because it avoids creating an intermediate array
  • For very deep nesting, use flatten(n) after map instead
  • When the block returns non-array values, flat_map behaves identically to map

Return Value

Always returns a flat (one-dimensional) array:

[].flat_map { |x| x }           # => []

[[1, 2], [3, 4]].flat_map { |x| x }  # => [1, 2, 3, 4]

Edge Cases

Block returns nil or false:

[1, 2, 3].flat_map { |n| nil }
# => [nil, nil, nil]

[1, 2, 3].flat_map { |n| false }
# => [false, false, false]

Empty arrays in result are preserved then flattened:

[1, 2, 3].flat_map { |n| n.odd? ? [] : [n] }
# => [2]

See Also