[英]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.