2014-01-22 92 views
1

我正在數組中創建一個哈希列表,並且希望在它們相同的情況下保留一個計數。計算Ruby數組中的對象

下面是一個例子散的樣子:

data = { 
    s: y.id, 
    t: z.id, 
    count: 0 
} 

我循環通過一堆這些散列和推動他們到一個列表。我希望這樣,當st的值已經存在於列表中的一個散列中時,count將會增加。

讓我澄清。假設這是我@list

@list = [ 
    { 
     s: 1, 
     t: 2, 
     count: 5 
    }, 
    { 
     s: 1, 
     t: 3, 
     count: 5 
    } 
] 

現在假設,我想下面的哈希推到列表:

data = { 
    s: 1, 
    t: 2, 
    count: 0 
} 

@list的結果應該是這樣的,因爲與s==1t==2已散存在於列表:

@list = [ 
    { 
     s: 1, 
     t: 2, 
     count: 6 
    }, 
    { 
     s: 1, 
     t: 3, 
     count: 5 
    } 

]

這是我目前所在的地方。

@final = [] 

while widgets.count > 1 
    widget = widgets.shift 
    widgets.each do |w| 
     data = { 
      s: widget.id, 
      t: w.id, 
      count: 0 
     } 
     @final << data 
    end 
end 

這只是將所有的排列到列表中,但我想,以防止複本時st是相同的,只是增加count

我希望我很清楚。

任何建議將不勝感激。

+1

有一個看看[這個問題](http://stackoverflow.com/questions/4351793/is-there-a-bag-implementation-in-ruby)爲計數集的通用實現。 – Sebastian

+0

一些測試會避免混淆:) – Rimian

+0

我已經添加了一個去它,因爲我認爲你已經解釋了它 - 測試將是有用的,這是真的:-) –

回答

1

我會做這樣的(假設我理解正確的問題):

def add_hash(data) 
    h, i = @list.each_with_index.find {|h,i| data[:s]==h[:s] && data[:t]==h[:t]} 
    if h 
    @list[i][:count] += 1 
    else 
    data[:count] = 1 
    @list << data 
    end 
end 

add_hash({ s: 1, t: 3, count: 0 }) 
@list # @list => [{:s=>1, :t=>2, :count=>5}, {:s=>1, :t=>3, :count=>6}] 

add_hash({ s: 2, t: 3, count: 0 }) 
@list # @list # => [{:s=>1, :t=>2, :count=>5}, {:s=>1, :t=>3, :count=>5}, 
        {:s=>2, :t=>3, :count=>1}] 

如果你可以改變@list,可考慮將其散列:

@hash = { { s: 1, t: 2 } => 5, { s: 1, t: 3 } => 5 } 
0

不知道我是否正確intepreting你的問題,但如果你想在每data哈希count屬性遞增時data.s == data.t,這應該做的伎倆:

@final = [] 

while widgets.count > 1 
    widget = widgets.shift 
    widgets.each do |w| 
     data = { 
      s: widget.id, 
      t: w.id, 
      count: 0 
     } 
     if data.s == data.t 
      data.count += 1 
     end 
     @final << data 
    end 
end 
+0

這很接近。我的意思是當data.s和data.t已經存在於@final數組中的現有對象時。在這種情況下,我想簡單地增加計數。 –

+0

我剛剛更新了我的帖子,以便更清楚。對困惑感到抱歉。 –

1

如果我得到你的問題的權利您可以在列表中使用find方法,並在其中指定要匹配的條件(s和t的值已存在於@final列表中)。
這是一個直接使用列表和哈希的例子。

widgets = [{s:1, t:2, count:0}, {s: 1, t:2, count:0}, {s: 1, t:2, count:0},  
{s:1, t:3, count:0}, {s:1, t:3, count:0}]  
@final = []  

widgets.each do |widget|  
    res = @final.find {|obj| obj[:s] == widget[:s] && obj[:t] == widget[:t] }  
    if res.nil?  
    widget[:count] = 1  
    @final << widget  
    else  
    res[:count] += 1  
    end  
end  

puts @final.inspect 

而從這個代碼的答案是

[{:s=>1, :t=>2, :count=>3}, {:s=>1, :t=>3, :count=>2}] 

預期

0
def reduce_matches(collection) 
    result.reduce([]) do |arr, element| 
    matching(arr, element) ? matching[:count] += 1 : arr << element 
    arr 
    end 
end 

def matching(coll, candidate) 
    coll.detect do |element| 
    element[:s] == candidate[:s] && element[:t] == candidate[:t] 
    end 
end 

現在您可以鍵入:

reduce_matches(widgets) 

它給你你需要什麼。例如,如果

widgets = [ 
    { 
    s: 1, 
    t: 2, 
    count: 0 
    }, 
    { 
    s: 2, 
    t: 3, 
    count: 0 
    }, 
    { 
    s: 1, 
    t: 2, 
    count: 0 
    }, 
] 

然後

reduce_matches(widgets) = [ 
    { 
    s: 1, 
    t: 2, 
    count: 1 
    }, 
    { 
    s: 2, 
    t: 3, 
    count: 0 
    } 
] 

想增加新的元素添加到小部件?

widgets << new_element 
reduce_matches(widgets)