2011-03-09 8 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)를 할 수 있다고 말하고 싶습니다! –

9

는 1.9.2 이후 Array#uniq (및 uniq!)는 블록이므로 uniq_by 대한 더 이상의 필요성을 걸린다.

+2

http://ruby-doc.org/core-1.9.2/Array.html#method-i-uniq이 확인합니다. –

+0

루비 1.9.2p180 블록이 uniq_by만큼 안정적으로 작동하지 않는 것처럼 보이지만, 문제가 무엇인지 파악하기 위해 광범위한 테스트를 수행하지는 않았다. – Kevin

+0

그리고 'require'backports '가있는 이전 루비에서 사용할 수 있습니다. –

관련 문제