Bunu yapmanın üç yolu vardır. (Burada
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
:
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}
adımları birleştirilen iki karma mevcut anahtarların değerlerini belirlemek için bir bloğu kullanıldığı Hash#update hazırlayınız aka merge!
), her iki karmada bulunan anahtarların değerlerini belirlemek için { |_,o,v| o+v }
satırını kullanır. İlk blok değişkeni (kullanılmayan ve bu nedenle _
yerel değişkeni ile temsil edilebilir) anahtardır, ikincisi (o
, "eski" için) anahtarın değeri h
ve üçüncü (n
, "new"), anahtarın g
'daki değeridir.
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
değişken blok ile temsil edilen sıfır varsayılan değer boş bir karma oluşturan bir sayma HASH kullanın. Bu demektir ki, h
karması k
anahtarına sahip değilse, h[k]
varsayılan değeri döndürür (ancak karmayı değiştirmez).
h[k] = h[k] + g[k]
h
ise sağ tarafında bir kilit k
, h[k]
nedenle 0
ile değiştirilir yok: için h[k] += g[k]
yukarıda genişler.
Sum değerleri ve Yakut v1.9 + kullanıyor ve anahtarlar her karma aynı sırada olmasını garanti o zaman bir karma
dönüştürmek, bu yapılabilir bir üçüncü yol gibidir aşağıdaki gibidir: (yukarıdaki b
başlayarak)
["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}
adımlar şunlardır:
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}
nesnenin verilmezse 'players', daha iyi olabilir bunu bir karma olarak temsil etmek için: '{" Angel Cabrera "=> {" skoru "=> 2," vuruş "=> 146," mermi "=> 3}, ...}'. 'Nil' değerini içeren 'oyuncuların' öğeleriyle ne yapmak istediğinizi açıklamalısınız.Onların atlanacağını farz ettim, ama başlangıçta, 'nil' kelimesini fark etmedim, bu da benim kodumda bir hatayla sonuçlandı. –