参数化数组#uniq(即uniq_by)

时间:2011-03-09 20:40:21

标签: ruby arrays

如果不是从数组中删除重复元素,我想删除具有共同特定属性的元素,该怎么办?

具体来说,我想从具有重复“精华”的数组中删除所有字符串,其中精华定义如下:

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)

实现这一目标的最佳方法是什么?

3 个答案:

答案 0 :(得分:10)

从1.9.2开始,Array#uniq(和uniq!)占用一个区块,因此不再需要uniq_by

答案 1 :(得分:4)

Activesupport有Array#uniq_by,这是代码:

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

Facets还有一个Enumerable#uniq_by

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

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