计算Ruby数组中的对象

时间:2014-01-22 01:44:27

标签: 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时阻止重复。

我希望我很清楚。

任何建议都将不胜感激。

4 个答案:

答案 0 :(得分:1)

如果我的问题是正确的,你可以使用list中的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}]  

按预期

答案 1 :(得分: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 }

答案 2 :(得分:0)

不确定我是否正确解答了您的问题,但是如果您希望count中每个data哈希中的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

答案 3 :(得分: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)