4

I have an array like the following

[
  [[0, :a], [2, :b]],
  [3, :c],
  [4, :d],
  [[5, :e], [6, :f], [7, :g]]
]

That is, an Array of elements that are either (1) 2-element Arrays, or (2) an Array of 2-element Arrays.

I am trying to find an elegant way to "flatten" this array such that elements that are (2) get expanded out into root-level elements. In this example:

[[0, :a], [2, :b], [3, :c], [4, :d], [5, :e], [6, :f], [7, :g]]

This is almost like using Array#flatten(depth), except depth needs to work from the inside out, rather than the outside in.

The actual arrays can get very large, so I do not want to push (<<) elements onto a new Array in a loop for performance reasons. For some reason I cannot think of how to use any combination of map, flatten, flat_map, or other more efficient Enumerable methods to accomplish this without writing a C++-style preallocate-and-populate loop. Can anyone think of a more Rubyist way to do this?

0

2 Answers 2

10

One way to do is:

array.flatten.each_slice(2).to_a
Sign up to request clarification or add additional context in comments.

Comments

1

Posting another solution here for posterity:

array.flat_map{|el| el.first.is_a?(Array) ? el : [el]}

This solution also handles if the innermost Arrays are of variable length -- that is, the total Array is an Array of (1) n-element Arrays or (2) Arrays of n-element Arrays, where n is not necessarily the same for any given element. For example

[
  [1,2,3],
  [[4,5], [6,7,8,9]]
]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.