簡體   English   中英

Ruby-按鍵對哈希數組進行分組

[英]Ruby - Group an array of hashes by key

我有一個哈希數組(已編輯 ):

data = [
    {id: 1, name: "Amy", win: 1, defeat: 0},
    {id: 1, name: "Amy", win: 1, defeat: 3},
    {id: 2, name: "Carl", win: 0, defeat: 1},
    {id: 2, name: "Carl", win: 2, defeat: 1}
]

如何使用鍵“名稱”作為參考來分組或合並成類似的內容:

data = [
    {id: 1, name: "Amy", win: 2, defeat: 3},
    {id: 2, name: "Carl", win: 2, defeat: 2}
]

編輯后,我忘了提及我也無法添加的ID。

這是我的嘗試

#!/usr/bin/env ruby

data = [
    {"name"=> "Amy", "win" => 1, "defeat" => 0},
    {"name"=> "Amy", "win" => 1, "defeat" => 3},
    {"name"=> "Carl", "win" => 0, "defeat" => 1},
    {"name"=> "Carl", "win" => 2, "defeat" => 1}
]

merged_hash = data.group_by { |h| h['name'] }.map do |_,val| 
  val.inject do |h1,h2| 
    h1.merge(h2) do |k,o,n|
      k == 'name' ? o : o + n 
    end
  end
end

merged_hash
# => [{"name"=>"Amy", "win"=>2, "defeat"=>3},
#     {"name"=>"Carl", "win"=>2, "defeat"=>2}]

回答編輯過的帖子:-

#!/usr/bin/env ruby

data = [
    {id: 1, name: "Amy", win: 1, defeat: 0},
    {id: 1, name: "Amy", win: 1, defeat: 3},
    {id: 2, name: "Carl", win: 0, defeat: 1},
    {id: 2, name: "Carl", win: 2, defeat: 1}
]

merged_hash = data.group_by { |h| h.values_at(:name, :id) }.map do |_,val| 
  val.inject do |h1,h2| 
    h1.merge(h2) do |k,o,n|
      %i(id name).include?(k) ? o : o + n 
    end
  end
end

merged_hash
# => [{:id=>1, :name=>"Amy", :win=>2, :defeat=>3},
#     {:id=>2, :name=>"Carl", :win=>2, :defeat=>2}]

您可以使用each_with_object和具有適當默認值的Hash-memo一次完成該操作。 例如:

data.each_with_object(Hash.new { |h, k| h[k] = { :id => k.first, :name => k.last, :win => 0, :defeat => 0 } }) do |h, m|
  k = h.values_at(:id, :name)
  m[k][:win   ] += h[:win   ]
  m[k][:defeat] += h[:defeat]
end.values

基本技巧是緩存由適當的鍵(在本例中為[ h[:id], h[:name] ]索引的結果),並使用值存儲所要存儲的內容。 m Hash上的默認proc會自動保留緩存的值,然后您可以在迭代期間應用簡單的求和。 然后調用最終values以解開緩存。

可以使用group_by好地方

result = []
data.group_by{|d| d[:id]}.each do {|name, records|
  win = 0
  defeat = 0

  records.each do |r|
    win += r[:win]
    defeat += r[:defeat]
  end
  f = records.first
  results << {:id => f[:id], :name => f[:name], :win => win, :defeat => defeat}
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM