【问题标题】:Flatten Hash while Iterating over hash's array elements. Ruby在迭代散列的数组元素时展平散列。红宝石
【发布时间】:2013-10-22 22:32:45
【问题描述】:

输入哈希可以包含任何数组和哈希(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}]`

【问题讨论】:

  • 我已经使用递归散列展平了输入散列。如果该值是一个数组,它会循环通过将 {theKey => theKeysValue} 推送到一个数组中以供以后访问。

标签: ruby arrays hash nested


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2010-12-23
    • 1970-01-01
    • 2019-11-03
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多