2015-04-03 127 views
1

結合我有散列的這樣一個數組:如何將多個散列值的數組中有相同鍵

[{"apple"=>5}, {"banana"=>4}, {"orange"=>6}, {"apple"=>4}, {"orange"=>2}] 

我如何到達:

[{"apple"=>9}, {"banana"=>4}, {"orange"=>8}] 
+0

向我們展示您到目前爲止所擁有的。 – fuesika 2015-04-04 01:15:12

回答

2

還有:

cache = Hash.new { |h, k| h[k] = { k => 0 } } 
aoh.flat_map(&:to_a) 
    .each_with_object(cache) { |(k,v),h| h[k][k] += v } 
    .values 

或者更多條要更清晰一點:

cache = Hash.new { |h, k| h[k] = { k => 0 } } 
sum  = -> ((k, v), h) { h[k][k] += v } 
summary = aoh.flat_map(&:to_a) 
      .each_with_object(cache, &sum) 
      .values 

的有些奇怪的看着cache哈希沒有馬上兩件事情:

  1. 保持跟蹤其鍵中迄今爲止已經看到哪些鍵。
  2. 跟蹤我們想要的最終結果的值。
+1

這很可愛....... – 2015-04-03 23:32:06

+0

@CarySwoveland謝謝。在「現實生活」中,我可能會使用包裝在一個很好命名的方法中的「更多部分」版本。我非常喜歡「使用lambda而不是塊,以便它可以有名稱」技巧。 – 2015-04-04 00:14:29

+0

我注意到了。 「......在他的腦海中,他有一個lambda,EIEIO,在這裏有一個'call''''',''''''''','''這裏有一個'()', ',到處都是'電話號碼','電話號碼...... – 2015-04-04 01:26:52

1

有許多方式,你會很快看到。這裏有一個:

arr = [{"apple"=>5}, {"banana"=>4}, {"orange"=>6}, {"apple"=>4}, {"orange"=>2}] 

arr.flat_map(&:to_a) 
    .group_by(&:first) 
    .map { |k,a| { k=>(a.reduce(0) { |tot,(_,v)| tot+v }) } } 
    #=> [{"apple"=>9}, {"banana"=>4}, {"orange"=>8}] 

步驟:

a = arr.flat_map(&:to_a) 
    #=> [["apple",5], ["banana",4], ["orange",6], ["apple",4], ["orange",2]] 
b = a.group_by(&:first) 
    #=> {"apple"=>[["apple", 5], ["apple", 4]], 
    # "banana"=>[["banana", 4]], 
    # "orange"=>[["orange", 6], ["orange", 2]]} 
b.map { |k,a| { k=>(a.reduce(0) { |tot,(_,v)| tot+v }) } } 
    #=> [{"apple"=>9}, {"banana"=>4}, {"orange"=>8}] 

讓我們來仔細看看b.map

enum = b.map 
    #=> #<Enumerator: { 
    #  "apple"=>[["apple", 5], ["apple", 4]], 
    #  "banana"=>[["banana", 4]], 
    #  "orange"=>[["orange", 6], ["orange", 2]] 
    # }:map> 

enum第一個元素傳遞(通過Enumerator#each,進而調用Array#each)添加到塊並分配給塊變量。我們可以模擬,使用Enumerator#next

k,a = enum.next 
    #=> ["apple", [["apple", 5], ["apple", 4]]] 
k #=> "apple" 
a #=> [["apple", 5], ["apple", 4]] 

要計算:

c = a.reduce(0) { |tot,(_,v)| tot+v } 
    #=> 9 

a第一元件被傳遞到塊和塊變量被分配:

tot, (_,v) = 0, ["apple", 5] 
    #=> [0, ["apple", 5]] 
tot #=> 0 
v #=> 5 

我們然後計算:

tot + 5 
    #=> 0+5 => 5 

返回reduce成爲更新值tot。的a第二值是在通過:

tot, (_,v) = 5, ["apple", 4] 
tot #=> 5 
v #=> 4 

,我們計算和返回:

tot+4 
    # 5+4 => 9 

這樣:

{ k=>tot } 
    #=> { "apple"=>9 } 

a所述第一元件的所映射的值。其餘映射值的計算方法相似。

相關問題