2015-01-09 88 views
0

我有一个散列,由.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个散列每个键:

# {: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班轮)和有效的方式(没有哈希重新创建)。

回答

2

grouped_hash.each_value(&:uniq)

根据AR对象,Rails的故意代表平等检查标识列。如果您想知道两个AR对象包含相同的值,则比较两个调用#attributes的结果。

1

不完全的一行(尽管你可以在一行写太):

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

我'已经更新了一个问题,以免被'id'弄糊涂并且证明每个对象中都有其他字段,所以'uniq'将不起作用 –

+0

'uniq(&:fid)'怎么样? (更新回答) – katafrakt

+0

谢谢!我明白了!你的解决方案重新创建一个哈希,所以我把它与@Tensho答案结合起来,得到我想要的 –

0

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

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