来自嵌套哈希的Ruby总和

时间:2016-04-09 16:44:09

标签: ruby-on-rails ruby

如何从以下数组返回总分,笔画和回合?

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

如何返回给定上面数组的笔画总和?

2 个答案:

答案 0 :(得分:2)

使用此代码:

@total= 0
players.each do |x|
a= x.values[0]
if a.class == Hash
  @total += a["strokes"]
end
end

puts @total

答案 1 :(得分:2)

以下是三种方法。

使用Hash#update的形式使用块来确定合并的两个哈希中存在的键的值

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表示)是关键,第二个(h,对于" old")是n和第三个(g中的键值," new")是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会被["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} 替换。

求和值,然后转换为哈希

如果您使用的是Ruby v1.9 +并且保证密钥在每个哈希中具有相同的顺序,则可以采用的第三种方式如下:

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} 开始)是:

{{1}}