按键值对合并哈希数组

时间:2018-09-27 13:22:35

标签: ruby hash key-value

我有一系列哈希,如下所示:

[
  {'abc_id'=>'1234', 'def_id'=>[]},
  {'abc_id'=>'5678', 'def_id'=>['11', '22']},
  {'abc_id'=>'1234', 'def_id'=>['33', '44']},
  {'abc_id'=>'5678', 'def_id'=>['55', '66']}
]

我正在尝试将具有相同键值对的多个哈希组合到一个哈希中。因此,我们有两对'abc_id'键具有相同的值,如下所示:

  • {'abc_id'=>'1234', 'def_id'=>[]}{'abc_id'=>'1234', 'def_id'=>['33', '44']}
  • {'abc_id'=>'5678', 'def_id'=>['11', '22']}{'abc_id'=>'5678', 'def_id'=>['55', '66']}

我希望将具有相同键值对的多个哈希合并到一个单独的哈希中。对于上述两对,它们应该分别为:

  • {'abc_id'=>'1234', 'def_id'=>['33', '44']}
  • {'abc_id'=>'5678', 'def_id'=>['11', '22', '55', '66']}

3 个答案:

答案 0 :(得分:1)

或多或少的通用和可扩展变体将是:

input.
  group_by { |h| h['abc_id'] }.
  map do |k, v|
    v.reduce do |acc, arr|
      #  use `+` instead of `|` to save duplicates  ⇓⇓⇓
      acc.merge(arr) { |_, v1, v2| Array === v1 ? v1 | v2 : v1 }
    end
  end
#⇒ [{"abc_id"=>"1234", "def_id"=>["33", "44"]},
#   {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]

答案 1 :(得分:0)

更多选择:

array
  .map.with_object({}) { |h, hh| hh[h['abc_id']].nil? ? hh[h['abc_id']] = h['def_id'] : hh[h['abc_id']] += h['def_id'] }
  .map{ |k, v| {'abc_id' => k, 'def_id' => v} }

第一部分返回

# {"1234"=>["33", "44"], "5678"=>["11", "22", "55", "66"]}

第二部分重建原始结构,返回:

#=> [{"abc_id"=>"1234", "def_id"=>["33", "44"]}, {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]

答案 2 :(得分:0)

可以使用Hash#update(又名merge!)和Hash#merge的形式,它们采用一个块来确定合并的两个哈希中存在的键的值。这里需要在两个级别上完成。

arr是问题中给出的数组,这些方法的用法如下。

arr.each_with_object({}) do |g,h|
  h.update(g['abc_id']=>g) do |_,o,n|
    o.merge(n) { |k,oo,nn| k=='def_id' ? oo+nn : oo }
  end
end.values
  #=> [{"abc_id"=>"1234", "def_id"=>["33", "44"]},
  #    {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]

有关块变量_onkoonn的解释,请参阅文档。我用下划线表示通用密钥  与update一起使用,以告诉读者块计算中没有使用它。

请注意,Hash#values的接收者如下。

{ "1234"=>{ "abc_id"=>"1234", "def_id"=>["33", "44"] },
  "5678"=>{ "abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"] } }