[英]Ruby sum from nested hash
如何從以下數組中返回總分,筆划和回合?
players = [{"Angel Cabrera"=>{"score"=>2, "strokes"=>146, "rounds"=>3}},
{"Jason Day"=>{"score"=>1, "strokes"=>145, "rounds"=>3}},
{"Bryson DeChambeau"=>{"score"=>0, "strokes"=>144, "rounds"=>3}},
{"Sergio Garcia"=>{"score"=>0, "strokes"=>144, "rounds"=>3}},
{"Ian Poulter"=>{"score"=>5, "strokes"=>162, "rounds"=>3}},
{"Vijay Singh"=>nil},
{"Jordan Spieth"=>{"score"=>-4, "strokes"=>140, "rounds"=>3}}]
我可以通過執行以下操作來中風,但是我知道這不是最好的方法。
players.each do |x|
x.values()[0]["strokes"]
end
給定上面的數組,如何返回筆畫的總和?
使用此代碼:
@total= 0
players.each do |x|
a= x.values[0]
if a.class == Hash
@total += a["strokes"]
end
end
puts @total
這是三種方法。
使用采用塊的Hash#update形式來確定合並的兩個哈希中存在的鍵的值
players.map { |g| g.first.last }.
compact.
each_with_object({}) { |g,h| h.update(g) { |_,o,v| o+v } }
#=> {"score"=>4, "strokes"=>881, "rounds"=>18}
步驟:
a = players.map { |g| g.first.last }
#=> [{"score"=> 2, "strokes"=>146, "rounds"=>3},
# {"score"=> 1, "strokes"=>145, "rounds"=>3},
# {"score"=> 0, "strokes"=>144, "rounds"=>3},
# {"score"=> 0, "strokes"=>144, "rounds"=>3},
# {"score"=> 5, "strokes"=>162, "rounds"=>3},
# nil,
# {"score"=>-4, "strokes"=>140, "rounds"=>3}]
b = a.compact
#=> [{"score"=> 2, "strokes"=>146, "rounds"=>3},
# {"score"=> 1, "strokes"=>145, "rounds"=>3},
# {"score"=> 0, "strokes"=>144, "rounds"=>3},
# {"score"=> 0, "strokes"=>144, "rounds"=>3},
# {"score"=> 5, "strokes"=>162, "rounds"=>3},
# {"score"=>-4, "strokes"=>140, "rounds"=>3}]
b.each_with_object({}) { |g,h| h.update(g) { |_,o,v| o+v } }
#=> {"score"=>4, "strokes"=>881, "rounds"=>18}
在這里, Hash#update
(又名merge!
)使用塊{ |_,o,v| o+v }
{ |_,o,v| o+v }
)來確定兩個哈希中都存在的鍵的值。 第一個塊變量(未使用,因此可以用局部變量_
)是鍵,第二個( o
,表示“ old”)是鍵在h
的值,第三個( n
,表示“ new”)是g
鍵的值。
使用計數哈希
players.map { |g| g.first.last }.
compact.
each_with_object(Hash.new(0)) { |g,h| g.keys.each { |k| h[k] += g[k] } }
Hash.new(0)
創建一個默認值為零的空哈希,由塊變量g
。 這意味着,如果哈希h
沒有鍵k
,則h[k]
返回默認值(但不會更改哈希)。 h[k] += g[k]
擴展為:
h[k] = h[k] + g[k]
如果h
沒有密鑰k
,那么右側的h[k]
因此被0
代替。
對值求和,然后轉換為哈希
如果您使用的是Ruby v1.9 +,並且確保每個哈希中的鍵具有相同的順序,則可以采用的第三種方法如下:
["scores", "strokes", "rounds"].zip(
players.map { |g| g.first.last }.
compact.
map(&:values).
transpose.
map { |arr| arr.reduce(:+) }
).to_h
#=> {"scores"=>4, "strokes"=>881, "rounds"=>18}
步驟(從上面的b
開始)是:
c = b.map(&:values)
#=> [[ 2, 146, 3],
# [ 1, 145, 3],
# [ 0, 144, 3],
# [ 0, 144, 3],
# [ 5, 162, 3],
# [-4, 140, 3]]
d = c.transpose
#=> [[ 2, 1, 0, 0, 5, -4],
# [146, 145, 144, 144, 162, 140],
# [ 3, 3, 3, 3, 3, 3]]
totals = d.map { |arr| arr.reduce(:+) }
#=> [4, 881, 18]
e = ["scores", "strokes", "rounds"].zip(totals)
#=> [["scores", 4], ["strokes", 881], ["rounds", 18]]
e.to_h
#=> {"scores"=>4, "strokes"=>881, "rounds"=>18}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.