我有一个哈希数组
[{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>10},
{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>10},
{:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}]
如何求和pages
值,仅保留唯一键?
例如:
[{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>20},
{:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}]
答案 0 :(得分:2)
让我们按ID分组,并将每个结果映射到一个结构,其中页面是该ID的所有页面的总和。
array.
group_by { |item| item[:id] }.
map do |id, items|
page_sum = items.sum { |i| i[:pages] }
Hash[:id, id, :book, items.first[:book], :pages, page_sum]
end
答案 1 :(得分:1)
arr = [
{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>10},
{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>10},
{:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}
]
arr.each_with_object({}) do |g,h|
h.update(g[:id]=>g) { |_,o,n| o.merge(pages: o[:pages] + n[:pages]) }
end.values
#=> [{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>30},
# {:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}]
请注意values
的接收者等于
{1=>{:id=>1, :book=>{:title=>"title1", :desc=>"title1", :author=>"title1"}, :pages=>30},
2=>{:id=>2, :book=>{:title=>"title2", :desc=>"title2", :author=>"title2"}, :pages=>30}}
这使用Hash#update(也称为merge!
)形式,并使用了该块
{ |_,o,n| o.merge(pages: o[:pages] + n[:pages]) }
确定合并的两个哈希中存在的键(块变量_
)的值。有关块变量o
和n
的说明,请参阅文档。
Hash#update
和Enumerable#group_by是处理此类问题时通常采用的两种方法。都可以使用。它们的效率大致相等,因此选择很大程度上是个人喜好之一。