rubyguides

Array#flatten

arr.flatten(depth=nil) -> array

.flatten returns a new array with all nested arrays recursively collapsed into a single flat array.

Syntax

array.flatten      # flatten all levels
array.flatten(1)   # flatten only one level deep
array.flatten(2)   # flatten two levels deep

The depth argument is what makes flatten more flexible than a simple recursive collapse. When you pass nil or omit the argument entirely, every level of nesting is removed. When you pass an integer, only that many levels are collapsed, leaving deeper nesting intact for later code that may still need it.

Parameters

ParameterTypeDefaultDescription
depthInteger or nilnilHow many levels to flatten. nil or negative flattens all levels.

Examples

Basic usage

nested = [1, [2, 3], [4, [5, 6]]]

nested.flatten
# => [1, 2, 3, 4, 5, 6]

Without arguments, .flatten recursively flattens all nested arrays.

Without arguments, flatten recursively collapses all nested arrays into a single one-dimensional list. This is the most common usage because most code that reaches for flatten simply wants everything in one level, with no concern for how deep the original nesting was.

Controlling depth

nested = [1, [2, [3, [4]]]]

nested.flatten(0)
# => [1, [2, [3, [4]]]]   # no flattening

nested.flatten(1)
# => [1, 2, [3, [4]]]    # flatten one level

nested.flatten(2)
# => [1, 2, 3, [4]]      # flatten two levels

Passing an integer controls how many levels of nesting to collapse.

Passing an integer controls how many levels of nesting to collapse, which is useful when the outer structure still matters but the inner layers are getting in the way. A depth of 1 removes only one layer while deeper values let you collapse further without tossing every level at once.

Common Patterns

Converting tree structures to lists

tree = [1, [2, [3, [4, [5]]]]]
tree.flatten
# => [1, 2, 3, 4, 5]

Converting tree structures to lists is one of the most natural uses for flatten. The method collapses arbitrarily deep nesting into a single sequence, which is exactly what you want when the tree shape was only a temporary organization and the final consumer expects a flat collection.

Flattening after mapping

matrix = [[1, 2], [3, 4], [5, 6]]

matrix.map { |row| row.map { |n| n * 2 } }.flatten
# => [2, 4, 6, 8, 10, 12]

Mapping and then flattening is a common pipeline pattern, but it creates an intermediate array that flat_map can avoid. For simple one-level transformations, consider whether flat_map expresses the same intent with one fewer method call and one fewer allocation.

Handling mixed data

mixed = [1, [2, 3], {a: 1}, [4, [5]]]
mixed.flatten
# => [1, 2, 3, {:a=>1}, 4, 5]

Flatten when nesting is noise

flatten is a good fit when the nested structure is only there because values were grouped earlier in the pipeline. The method turns that structure back into a simple list, which can make later steps much easier to read. That is common after mapping, merging batches, or collecting values from a recursive walk. The important part is that flatten changes the shape of the array, so it should be used when a single list is the real goal rather than when the nesting carries meaning.

Choose the depth deliberately

The optional depth argument lets you decide how much nesting should remain. A depth of 1 only removes one layer, while a deeper value lets you collapse the array further without blowing away every level at once. That makes the method more flexible than a blanket recursive collapse. It also helps when the outer structure is still useful but the inner layers are getting in the way. The code stays clearer when the chosen depth matches the shape you actually need.

Remember that values stay the same

flatten creates a new array, but it does not clone nested objects for you. If the array contains hashes or other mutable values, those objects are still shared. That is usually fine, but it is worth keeping in mind when later code mutates one of the results and expects the source array to stay untouched at every level. In other words, flatten is about simplifying the container, not duplicating the entire object graph.

See Also