2011-04-29 5 views
6
a, b, c = 0, 1, 2 
[a, b, c].find(&:zero?) # => 0 

블록이 false를 반환하는 첫 번째 요소를 찾는 방법이 있습니까? 즉Ruby에서 find와 반대되는 메소드가 있습니까?

[a, b, c].the_method(&:zero?) # => 1 

, 그와 같은 방식으로 작동합니다 : 지금까지 내가이 작업을 수행하는 표준 방법이없는 말할 수

[a, b, c].reject(&:zero?).first 
+0

'거부 (...). 첫 번째 '는 당신이 겪은 것처럼 보입니다. - 그게 뭐가 잘못 됐나요? –

+3

_Proc_를 사용하면 어떨까요? '[a, b, c] .find {| i | i! = 0}' – konus

+2

@Joe 그 문제는 전체 컬렉션을 반복하고 모든 일치하는 값의 전체 배열을 만든 다음 모두 버리는 것입니다. 'find '의 장점은 첫 번째 일치하는 값을 찾자 마자 iterating을 멈추는 것입니다. – Phrogz

답변

9

is not를 기록 할 수 있지만 하나의 깨끗한 틱 방법 중 하나를 만들 수 있습니다

a = [0,2,1,0,3] 

module Enumerable 
    def first_not(&block) 
    find{ |x| !block[x] } 
    end 
end 

p a.first_not(&:zero?) 
#=> 2 

을 .. 불러야 끔찍-재미있는 해킹 방법 :

class Proc 
    def ! 
    proc{ |o,*a| !self[o,*a] } 
    end 
end 

p a.find(&!(:zero?.to_proc)) 
#=> 2 

... 나 정말 위험한 간결-하지만-방법 :

class Symbol 
    def ! 
    proc{ |o,*a| !o.send(self,*a) } 
    end 
end 

p a.find(&!:zero?) 
#=> 2 

하지만 난 그냥 까다로운 Symbol#to_proc 사용을 생략하고 당신이 원하는 말을 옹호하는 것 : 루비 2.0를 사용하는 경우

p a.find{ |i| !i.zero? } 
#=> 2 
+0

승리를위한 해킹 방법! =) – Aleksey

2

(즉 find_all을 주어 서로 참조를 거부 , find는 아무것도 참조하지 않습니다). 당신은 ((가) 너무 느린 거부 특히) 자주 필요한 경우 당신은 당신의 자신의

module Enumerable 

    def first_reject(&block) 
    find {|a| not (block.call(a)) } 
    end 

end 
+0

그러나 Phrogz는이 함수를 작성하는 것이 일반적으로 최선이라고 동의합니다 . –

2

것은, 당신이 겪고의 성능 저하없이 lazy.reject(&:zero?).first을 할 수 있습니다 전체 배열.

관련 문제