我有一个JSON,其中包含带有代码,名称和数量的产品项目。有时项目是重复的(相同的代码和名称,不同的数量(。我想将它们的数量汇总为一个。
前任:
从
{ items: [{ code: 1, name: 'A', quantity: 2.0 }, { code: 1, name: 'A', quantity: 3.0 }, { code: 2, name: 'B', quantity: 4.0 }] }
自
{ items: [{ code: 1, name: 'A', quantity: 5.0 }, { code: 2, name: 'B', quantity: 4.0 }] }
这应该有效:
items_hash = { items: [{ code: 1, name: 'A', quantity: 2.0 }, { code: 1, name: 'A', quantity: 3.0 }, { code: 2, name: 'B', quantity: 4.0 }] }
items_hash[:items] = items_hash[:items].each_with_object([]) do |item, collected_items|
if item_in_collected_items = collected_items.find { |i| i[:code] == item[:code] }
item_in_collected_items[:quantity] += item[:quantity]
else
collected_items << item
end
end
p items_hash
#=> { items: [{ code: 1, name: 'A', quantity: 5.0 }, { code: 2, name: 'B', quantity: 4.0 }] }
代码
def group_em(h)
h.transform_values do |a|
a.each_with_object({}) do |g,h|
h.update([g[:code], g[:name]]=>g) do |_,o,n|
g.merge(quantity: o[:quantity] + n[:quantity])
end
end.values
end
end
例子
h = { items: [{ code: 1, name: 'A', quantity: 2.0 },
{ code: 1, name: 'A', quantity: 3.0 },
{ code: 2, name: 'B', quantity: 4.0 }] }
group_em(h)
#=> { items: [{ code: 1, name: 'A', quantity: 5.0 },
# { code: 2, name: 'B', quantity: 4.0 }] }
h = { items: [{ code: 1, name: 'A', quantity: 2.0 },
{ code: 1, name: 'A', quantity: 3.0 },
{ code: 1, name: 'C', quantity: 6.0 },
{ code: 2, name: 'B', quantity: 4.0 }] }
group_em(h)
#=> {:items=>[{:code=>1, :name=>"A", :quantity=>5.0},
# {:code=>1, :name=>"C", :quantity=>6.0},
# {:code=>2, :name=>"B", :quantity=>4.0}]}
h = { items: [{ code: 1, name: 'A', quantity: 2.0 },
{ code: 1, name: 'A', quantity: 3.0 },
{ code: 1, name: 'C', quantity: 6.0 },
{ code: 2, name: 'B', quantity: 4.0 }],
returns: [{ code: 2, name: 'B', quantity: 1.0 },
{ code: 1, name: 'A', quantity: 3.0 },
{ code: 1, name: 'C', quantity: 1.0 },
{ code: 2, name: 'B', quantity: 2.0 }]
}
group_em(h)
#=> {:items=>[{:code=>1, :name=>"A", :quantity=>5.0},
# {:code=>1, :name=>"C", :quantity=>6.0},
# {:code=>2, :name=>"B", :quantity=>4.0}],
# :returns=>[{:code=>2, :name=>"B", :quantity=>3.0},
# {:code=>1, :name=>"A", :quantity=>3.0},
# {:code=>1, :name=>"C", :quantity=>1.0}]}
解释
请参阅哈希#transform_values,枚举#each_with_object,哈希#合并和哈希#更新(又名merge!
(的形式,它使用块来确定合并的两个哈希中存在的键的值。这里的块是:
do |_,o,n|
g.merge(quantity: o[:quantity] + n[:quantity])
end
三个块变量的值,_
、o
和n
,在文档中定义。我使用下划线(一个有效的局部变量(作为第一个变量 - 公共键 - 表示它未在块计算中使用。这是惯例。
请注意:
h.update([g[:code], g[:name]]=>g)
是以下的简写:
h.update({ [g[:code], g[:name]]=>g })