我有一个由以下形式的哈希组成的数组:
array = [
{"id": 1, "items": [{"item_code": 1, "qty": 2},{"item_code": 2, "qty": 2}]},
{"id": 2, "items": [{"item_code": 3, "qty": 2},{"item_code": 4, "qty": 2}]},
{"id": 1, "items": [{"item_code": 5, "qty": 2},{"item_code": 6, "qty": 2}]},
{"id": 2, "items": [{"item_code": 7, "qty": 2},{"item_code": 8, "qty": 2}]}
]
我们是否有任何方便的方法来根据ID合并项目?
预期输出:
array = [
{"id": 1, "items": [
{"item_code": 1, "qty": 2},
{"item_code": 2, "qty": 2},
{"item_code": 5, "qty": 2},
{"item_code": 6, "qty": 2}
]
},
{"id": 2, "items": [
{"item_code": 3, "qty": 2},
{"item_code": 4, "qty": 2},
{"item_code": 7, "qty": 2},
{"item_code": 8, "qty": 2}
]
}
]
我尝试了不符合输出格式的group_by。
答案 0 :(得分:2)
ary.group_by { |elem| elem[:id] }.
each_with_object([]) do |(id, grouped_ary), out|
out << { id: id, items: grouped_ary.map { |h| h[:items] }.reduce(:|) }
end
=> [{:id=>1, :items=>[{:item_code=>1, :qty=>2},
{:item_code=>2, :qty=>2},
{:item_code=>5, :qty=>2},
{:item_code=>6, :qty=>2}]},
{:id=>2, :items=>[{:item_code=>3, :qty=>2},
{:item_code=>4, :qty=>2},
{:item_code=>7, :qty=>2},
{:item_code=>8, :qty=>2}]}]
答案 1 :(得分:2)
不需要group_by
。直接从头开始使用each_with_object
。
array.
each_with_object({}) do |hash, acc|
acc[hash[:id]] ?
acc[hash[:id]][:items] |= hash[:items] :
acc[hash[:id]] = hash
end.values
#⇒ [{:id=>1, :items=>[{:item_code=>1, :qty=>2},
# {:item_code=>2, :qty=>2},
# {:item_code=>5, :qty=>2},
# {:item_code=>6, :qty=>2}]},
# {:id=>2, :items=>[{:item_code=>3, :qty=>2},
# {:item_code=>4, :qty=>2},
# {:item_code=>7, :qty=>2},
# {:item_code=>8, :qty=>2}]}]
答案 2 :(得分:1)
您可以结合使用group_by
和transform_values!
(对于后者,您需要Ruby 2.4.0及更高版本,否则可以使用each_with_object
,如@Jagdeep指出的那样)
array.group_by { |item| item[:id] }
.transform_values! { |v| v.flat_map { |subitem| subitem[:items] } }
.map { |(id, items)| Hash["id", id, "items", items] }
答案 3 :(得分:1)
首先,我映射ID,然后为每个ID用两个键进行哈希处理:ID和每个条目项的展平图:
result = array.group_by { |e| e[:id] }.map { |id, entries| {id: id, items: entries.flat_map { |entry| entry[:items] }} }
答案 4 :(得分:1)
array.each_with_object({}) { |g,h| h.update(g[:id]=>g[:items]) { |_,o,n| o+n } }.
map { |k,v| { id: k, items: v } }
#=> [{:id=>1, :items=>[{:item_code=>1, :qty=>2}, {:item_code=>2, :qty=>2},
# {:item_code=>5, :qty=>2}, {:item_code=>6, :qty=>2}]},
# {:id=>2, :items=>[{:item_code=>3, :qty=>2}, {:item_code=>4, :qty=>2},
# {:item_code=>7, :qty=>2}, {:item_code=>8, :qty=>2}]}]
第一步是:
array.each_with_object({}) { |g,h| h.update(g[:id]=>g[:items]) { |_,o,n| o+n } }
#=> {1=>[{:item_code=>1, :qty=>2}, {:item_code=>2, :qty=>2},
# {:item_code=>5, :qty=>2}, {:item_code=>6, :qty=>2}],
# 2=>[{:item_code=>3, :qty=>2}, {:item_code=>4, :qty=>2},
# {:item_code=>7, :qty=>2}, {:item_code=>8, :qty=>2}]}
这利用Hash#update(也称为merge!
)的形式,该形式采用一个块来确定两个合并的散列中存在的键的值。有关三个块变量的定义,请参见文档。
或者,可以写以下内容。
array.each_with_object({}) { |g,h| h.update(g[:id]=>g) { |_,o,n|
o.merge(n) { |k,oo,nn| k == :items ? oo+nn : oo } } }.values