2016-04-09 44 views
1

如何從下列數組中返回總分數,筆畫和回合?來自嵌套散列表的紅寶石總和

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 

我該如何返回給定數組上面的筆畫的總和?

+0

如果未給定對象'players',它可能是更好將其表示爲散列:'{「Angel Cabrera」=> {「score」=> 2,「strokes」=> 146,「rounds」=> 3},...}。你應該解釋一下你想要處理的元素包含'nil'值的'players'。我認爲他們將被跳過,但最初沒有注意到孤獨'nil',這導致了我的代碼中的一個錯誤。 –

回答

1

以下是這樣做的三種方式。

使用的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,對於「舊」)是h中的鍵的值,第三個(n,對於「新」)是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不具有關鍵kh[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} 
2

使用此代碼:

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

puts @total