通过键值对合并哈希数组
Merge an array of hashes by key-value pair
我有一个哈希数组如下:
[
{'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']}
或多或少的通用和可扩展变体是:
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"]}]
多一个选项:
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} }
第一部分returns
# {"1234"=>["33", "44"], "5678"=>["11", "22", "55", "66"]}
第二部分重建原来的结构,返回:
#=> [{"abc_id"=>"1234", "def_id"=>["33", "44"]}, {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]
可以使用 Hash#update (aka merge!
) and 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"]}]
有关块变量 _
、o
、n
、k
、oo
和 nn
的说明,请参阅文档.我用下划线来表示公共键
用 update
告诉 reader 它不用于块计算。
注意Hash#values的接收者如下
{ "1234"=>{ "abc_id"=>"1234", "def_id"=>["33", "44"] },
"5678"=>{ "abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"] } }
我有一个哈希数组如下:
[
{'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']}
或多或少的通用和可扩展变体是:
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"]}]
多一个选项:
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} }
第一部分returns
# {"1234"=>["33", "44"], "5678"=>["11", "22", "55", "66"]}
第二部分重建原来的结构,返回:
#=> [{"abc_id"=>"1234", "def_id"=>["33", "44"]}, {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]
可以使用 Hash#update (aka merge!
) and 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"]}]
有关块变量 _
、o
、n
、k
、oo
和 nn
的说明,请参阅文档.我用下划线来表示公共键
用 update
告诉 reader 它不用于块计算。
注意Hash#values的接收者如下
{ "1234"=>{ "abc_id"=>"1234", "def_id"=>["33", "44"] },
"5678"=>{ "abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"] } }