数组内散列值之和 In ruby
Sum of hash value inside the array In ruby
我有这样的数组
data =
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>4, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>1, :unitPrice=>5.76 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
如果 sku 相同,我需要对数量求和并删除重复项。所以输出应该是这样的:
data =
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>5, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
输入
data =
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>4, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>1, :unitPrice=>5.76 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
代码
p data.group_by { |x| x[:lineItemKey] }
.values
.map { |arr| arr.reduce { |h1, h2| h1.merge(h2) { |k, oldv, newv| k.eql?(:quantity) ? oldv += newv : oldv } } }
输出
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>5, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
data.each_with_object({}) do |g,h|
h.update(g[:lineItemKey]=>g) do |_k, old_hash, new_hash|
old_hash.merge(quantity: old_hash[:quantity] + new_hash[:quantity])
end
end.values
#=> [
# {:lineItemKey=>57, :sku=>"12GA-RIO", :name=>"12 Gauge",
# :quantity=>5, :unitPrice=>5.76},
# {:lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50", :name=>"22 Long",
# :quantity=>2, :unitPrice=>7.6},
# {:lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
# :name=>"300 BLK", :quantity=>1, :unitPrice=>31.2}
# ]
注意values
的接收者是
{
57=>{:lineItemKey=>57, :sku=>"12GA-RIO", :name=>"12 Gauge",
:quantity=>5, :unitPrice=>5.76},
168=>{:lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6},
236=>{:lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2}
}
这使用 Hash#update (a.k.a merge!
) 的形式,它使用一个块来计算合并的两个散列中存在的键的值。这个块是
do |_k, old_hash, new_hash|
old_hash.merge(quantity: old_hash[:quantity] + new_hash[:quantity])
end
有关三个块变量的定义,请参阅文档。 k
(公共键)之前的下划线是为了向 reader 发出信号,表明它不用于块计算(一种常见约定,通常只是单独的下划线)。
我有这样的数组
data =
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>4, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>1, :unitPrice=>5.76 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
如果 sku 相同,我需要对数量求和并删除重复项。所以输出应该是这样的:
data =
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>5, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
输入
data =
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>4, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>1, :unitPrice=>5.76 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
代码
p data.group_by { |x| x[:lineItemKey] }
.values
.map { |arr| arr.reduce { |h1, h2| h1.merge(h2) { |k, oldv, newv| k.eql?(:quantity) ? oldv += newv : oldv } } }
输出
[
{ :lineItemKey=>57, :sku=>"12GA-RIO",
:name=>"12 Gauge", :quantity=>5, :unitPrice=>5.76 },
{ :lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6 },
{ :lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2 }
]
data.each_with_object({}) do |g,h|
h.update(g[:lineItemKey]=>g) do |_k, old_hash, new_hash|
old_hash.merge(quantity: old_hash[:quantity] + new_hash[:quantity])
end
end.values
#=> [
# {:lineItemKey=>57, :sku=>"12GA-RIO", :name=>"12 Gauge",
# :quantity=>5, :unitPrice=>5.76},
# {:lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50", :name=>"22 Long",
# :quantity=>2, :unitPrice=>7.6},
# {:lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
# :name=>"300 BLK", :quantity=>1, :unitPrice=>31.2}
# ]
注意values
的接收者是
{
57=>{:lineItemKey=>57, :sku=>"12GA-RIO", :name=>"12 Gauge",
:quantity=>5, :unitPrice=>5.76},
168=>{:lineItemKey=>168, :sku=>"22LR-CAS-40-CPRN-50",
:name=>"22 Long", :quantity=>2, :unitPrice=>7.6},
236=>{:lineItemKey=>236, :sku=>"300BLK-UNWD-CTC-220-BTHP-20",
:name=>"300 BLK", :quantity=>1, :unitPrice=>31.2}
}
这使用 Hash#update (a.k.a merge!
) 的形式,它使用一个块来计算合并的两个散列中存在的键的值。这个块是
do |_k, old_hash, new_hash|
old_hash.merge(quantity: old_hash[:quantity] + new_hash[:quantity])
end
有关三个块变量的定义,请参阅文档。 k
(公共键)之前的下划线是为了向 reader 发出信号,表明它不用于块计算(一种常见约定,通常只是单独的下划线)。