2011-03-09 69 views
3

如果不是从数组中删除重复的元素,我想删除具有特定属性的元素?参数化数组#uniq(即,uniq_by)

具体来说,我想从数组中删除所有的字符串重复的“本质”,在本质上是这样定义的:

class String 
    def essence 
    downcase.gsub('&', 'and').gsub(/[^a-z0-9]/, '') 
    end 
end 

我想是这样的:

['a', 'A', 'b'].uniq_by(&:essence) 
# => ['a', 'b'] (or ['A', 'b']; I don't really care) 

有什么最好的方法来完成这个?

回答

4

的ActiveSupport有Array#uniq_by,这是代码:

class Array 
    def uniq_by 
    hash, array = {}, [] 
    each { |i| hash[yield(i)] ||= (array << i) } 
    array 
    end 
end 

刻面也有Enumerable#uniq_by

module Enumerable  
    def uniq_by 
    h = {} 
    inject([]) {|a,x| h[yield(x)] ||= a << x} 
    end  
end 
3

快速和肮脏的方式:

['a', 'A', 'b'].group_by {|i| i.essence}.values.map(&:first) 

和一些猴子补丁:

class Array 
    def uniq_by(&block) 
    group_by(&block).values.map(&:first) 
    end 
end 
+0

嘿,只是想评论说你实际上可以做'group_by(&:essence)',这样如果你想更新你的答案,你可以! – 2016-04-13 22:06:05

9

由于1.9.2,Array#uniq(和uniq!)取块,所以对于uniq_by不再需要。

+2

http://ruby-doc.org/core-1.9.2/Array.html#method-i-uniq证实了这一点。 – 2012-03-15 22:06:13

+0

为了防止其他人遇到这个问题,ruby 1.9.2p180与block的独特性似乎并不像uniq_by那样可靠,尽管我还没有做过大量的测试来弄清楚什么是问题。 – Kevin 2012-11-12 07:06:49

+0

并可以通过'require'backports''提供给更早的Rubies。 – 2013-02-06 21:39:03