Existe um método em Ruby que faz o oposto do achado?
-
27-10-2019 - |
Pergunta
a, b, c = 0, 1, 2
[a, b, c].find(&:zero?) # => 0
Existe algum método que encontra o primeiro elemento para o qual o bloco retornos falsos?
[a, b, c].the_method(&:zero?) # => 1
Em outras palavras, ele iria se comportar da mesma forma como:
[a, b, c].reject(&:zero?).first
Solução
não é , mas você pode criar um ou a maneira limpa-ish:
a = [0,2,1,0,3]
module Enumerable
def first_not(&block)
find{ |x| !block[x] }
end
end
p a.first_not(&:zero?)
#=> 2
... ou a forma como corte horrivelmente-divertido:
class Proc
def !
proc{ |o,*a| !self[o,*a] }
end
end
p a.find(&!(:zero?.to_proc))
#=> 2
... ou terse-mas-terrivelmente perigoso caminho:
class Symbol
def !
proc{ |o,*a| !o.send(self,*a) }
end
end
p a.find(&!:zero?)
#=> 2
Mas eu defendo apenas pular o uso Symbol#to_proc
complicado e dizendo o que você quer:
p a.find{ |i| !i.zero? }
#=> 2
Outras dicas
Tanto quanto eu posso dizer que não há um método padrão para fazer isso (uma vez que find_all e rejeitar referência um ao outro, mas Localizar não referência qualquer coisa). Se você precisar dele frequentemente (especialmente se a rejeitar é muito lento), você pode escrever seu próprio
module Enumerable
def first_reject(&block)
find {|a| not (block.call(a)) }
end
end
Se você está usando o Ruby 2.0, você pode ser capaz de fazer lazy.reject(&:zero?).first
sem a pena de passar por toda a gama de desempenho.