Home > Net >  Flatten Hash with Values of Arrays By Order of Index in Ruby
Flatten Hash with Values of Arrays By Order of Index in Ruby

Time:09-17

I'm trying to find a way to flatten a hash of arrays, such that the order of the elements are in order of index. So 1st element of every array gets picked up, then second, then third, and so on, and if there is no element of that index then move on to the next array instead of returning nil or something.

Example 1: {a: [1, 2, 3], b: [4, 5], c: [6, 7, 8, 9]}

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

Example 2: {i: ['A'], ii: ['B', 'C', 'D'], iii: ['E'], iv: ['F', 'G]}

Result: ['A', 'B', 'E', 'F', 'C', 'G', 'D']

CodePudding user response:

Here's one way:

arr = {a: [1, 2, 3], b: [4, 5], c: [6, 7, 8, 9]}
arr.values.
    map{|ar| ar Array.new(100)}.  # pad with nils
    inject{|a,ar| a.zip(ar)}.
    flatten.
    compact #=> [1, 4, 6, 2, 5, 7, 3, 8, 9]

it's pretty ugly though! In order to avoid the discarding of the elements of long arrays, pad them all with a lot of nils, and then discard the nils at the end with compact. You have to choose a padding length (I chose 100) that's "long enough" that elements are not discarded in the zip.

CodePudding user response:

I suggest:

def extract_values_ordered_by_index(hash)
  Array.new(hash.values.map(&:length).max) do |i| 
    hash.values.map { |array| array[i] } 
  end.flatten.compact
end

hash = {a: [1, 2, 3], b: [4, 5], c: [6, 7, 8, 9]}
extract_values_ordered_by_index(hash)
#=> [1, 4, 6, 2, 5, 7, 3, 8, 9]

hash = {i: ['A'], ii: ['B', 'C', 'D'], iii: ['E'], iv: ['F', 'G']}
extract_values_ordered_by_index(hash)
#=> ["A", "B", "E", "F", "C", "G", "D"]
  • Related