在迭代哈希的数组元素时展平哈希。红宝石

时间:2013-08-07 18:41:20

标签: ruby arrays hash nested

输入散列可以包含阵列和散列(AoA,AoH,HoH和HoA)的任何组合的嵌套。将哈希元素展平为具有_>的正确键和分隔符是没有问题的。

但是,当阵列进入图片时我遇到了麻烦,我需要抓住每个元素并将其粘贴到正确的键上,同时继续构建输出。最终输出应该是一维的哈希数组,唯一的区别是每个数组元素。

例如:

如果输入哈希是:     {:x => 333, :y => 13, :z => [1,2,{:zz => [40,50]},[10,20]], :a => {:o => "1", :p => "2"}}

最终结果应为:

`[{:x => 333, :y => 13, :z => 1, :z_>zz => 40, :a_>o => 1, a_>p => 2},  
 {:x => 333, :y => 13, :z => 1, :z_>zz => 50, :a_>o => 1, a_>p => 2},  
 {:x => 333, :y => 13, :z => 2, :z_>zz => 40, :a_>o => 1, a_>p => 2},  
 {:x => 333, :y => 13, :z => 2, :z_>zz => 50, :a_>o => 1, a_>p => 2},  
 {:x => 333, :y => 13, :z => 10, :z_>zz => 40, :a_>o => 1, a_>p => 2},  
 {:x => 333, :y => 13, :z => 10, :z_>zz => 50, :a_>o => 1, a_>p => 2},  
 {:x => 333, :y => 13, :z => 20, :z_>zz => 40, :a_>o => 1, a_>p => 2},  
 {:x => 333, :y => 13, :z => 20, :z_>zz => 50, :a_>o => 1, a_>p => 2}]`

1 个答案:

答案 0 :(得分:2)

这是漫长而复杂的,但至少它有效:

my_hash = {:x => 333, :y => 13, :z => [1,2,{:zz => [40,50]},[10,20]], :a => {:o => "1", :p => "2"}}


# Create Recursive function to get values:
def advance_hash_flattener(input, parent=[])
  case input
    when Hash then input.flat_map{|key, val|
      advance_hash_flattener(val, parent+[key])}
    when Array then input.flat_map{|x| advance_hash_flattener(x, parent)}
    else [parent.join('_>'), input]
  end
end

#Some small transformations for the last step:
first_step =  advance_hash_flattener(my_hash)
   .each_slice(2)
   .group_by{|x| x.first}
   .map{|x| [x.first, x.last.map(&:last)]}
p first_step #=> [["x", [333]], ["y", [13]], ["z", [1, 2, 10, 20]], ["z_>zz", [40, 50]], ["a_>o", ["1"]], ["a_>p", ["2"]]]

# Create an array of Hashes:
final_array = [Hash.new]
first_step.each do |key,values|
  new = []
  values.each do |val|
    if final_array.first.key?(key)
      final_copy = final_array.map{|x|x.clone}
      final_copy.each{|x| x[key] = val}
      new += final_copy
    else
      final_array.each{|x| x[key] = val}
    end
  end
  final_array += new
end
# result stored in final_array