2011-04-29 56 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

'拒絕(...)。第一個'看起來像你之後 - 這是什麼問題? – 2011-04-29 19:38:28

+3

怎麼樣使用_Proc_? '[a,b,c] .find {| i | i!= 0}' – konus 2011-04-29 19:45:43

+2

@Joe問題是你循環整個集合並創建一個完整的所有匹配值的數組,然後全部拋出。 'find'的美妙之處在於它一找到第一個匹配的值就停止迭代。 – Phrogz 2011-04-29 20:03:18

回答

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使用,說你想要什麼:

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

贏取黑客方式! =) – Aleksey 2017-02-03 14:29:28

2

(因爲find_all並拒絕相互借鑑,但是find沒有引用任何東西)。如果你需要頻繁(尤其是如果拒絕太慢),您可以編寫自己的

module Enumerable 

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

end 
+0

但是,我同意Phrogz的觀點,只是寫出函數通常是最好的。 – 2011-04-29 22:13:25

2

如果你使用Ruby 2.0,你可以做lazy.reject(&:zero?).first沒有經過去的性能損失整個陣列。

相關問題