分组哈希中的唯一对象

时间:2015-01-09 08:44:12

标签: ruby-on-rails ruby hash openstruct

我有一个由.group_by方法创建的哈希,字符串作为键,AR对象作为值。我想摆脱AR对象与重复字段(其他字段可能相同或不同)

澄清我创建此代码段的问题:

require 'ostruct'   

def os_new(fid); OpenStruct.new(fid: fid, rand: rand(100)); end                                                                                                                                              
a = [os_new(1), os_new(2), os_new(3)]                                                                                                                                                
b = [os_new(3), os_new(3), os_new(2)]                                                                                                                                                
c = [os_new(5), os_new(5), os_new(5), os_new(5)] 

grouped_hash = { a: a, b: b, c: c} 

grouped_hash这是:

# {:a=>[#<OpenStruct fid=1, rand=7>, #<OpenStruct fid=2, rand=50>, #<OpenStruct fid=3, rand=13>], 
#  :b=>[#<OpenStruct fid=3, rand=51>, #<OpenStruct fid=3, rand=58>, #<OpenStruct fid=2, rand=88>], 
#  :c=>[#<OpenStruct fid=5, rand=40>, #<OpenStruct fid=5, rand=8>, #<OpenStruct fid=5, rand=45>, #<OpenStruct fid=5, rand=72>]} 

现在,结果我希望每个键都有一个唯一fid s的哈希:

# {:a=>[#<OpenStruct fid=1, rand=7>, #<OpenStruct fid=2, rand=50>, #<OpenStruct fid=3, rand=13>], 
#  :b=>[#<OpenStruct fid=3, rand=51>, #<OpenStruct fid=2, rand=88>], 
#  :c=>[#<OpenStruct fid=5, rand=40>]} 

我的解决方案需要几个动作,看起来很难看。

grouped_hash.each_value do |value|                                                                                                                                                     
  fids = []
  value.delete_if do |object|
    if fids.include? object.fid                                                                                                                                                            
      true
    else                                                                                                                                                                                   
      fids << object.fid
      false
    end                                                                                                                                                                                
  end
end

我正在寻找最优雅(可能是1线)的高效方式(没有哈希重新创建)。

3 个答案:

答案 0 :(得分:2)

grouped_hash.each_value(&:uniq)

根据AR对象,Rails故意将相等性检查委托给标识列。如果你想知道两个AR对象包含相同的值,那么比较两个上调用#attributes的结果。

答案 1 :(得分:1)

不完全是单行(虽然你也可以把它写成一行):

grouped_hash.inject({}) do |hash, element|
  hash[element.first] = element.last.uniq(&:fid)
  hash
end

答案 2 :(得分:0)

通过合并Tenshokatafrakt(谢谢你们)的答案我做了这个:

grouped_hash.each_value { |v| v.uniq!(&:fid) }