使用公共属性联接 JSON

  • 本文关键字:JSON 属性 json ruby
  • 更新时间 :
  • 英文 :


我有一个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

三个块变量的值,_on,在文档中定义。我使用下划线(一个有效的局部变量(作为第一个变量 - 公共键 - 表示它未在块计算中使用。这是惯例。

请注意:

h.update([g[:code], g[:name]]=>g)

是以下的简写:

h.update({ [g[:code], g[:name]]=>g })

最新更新