2016-04-05 113 views
2

我需要一個類似於Array#select的函數,但是不僅傳遞數據項的塊,而且傳遞元素的索引(類似於Enumerable#each_with_index)。我嘗試這樣做:Ruby:組合枚舉器,製作一個新的枚舉器

class Array 
    def select_with_index 
    self.each_with_index.select {|*args| yield(*args)}.map(&:first) 
    end 
end 

這似乎確實工作:如預期在

["a", "a"] 

['a','b','a','a','c'].select_with_index {|letter,index| letter == 'a' && index > 1 } 

結果。然而,我不喜歡我的解決方案是,那個提供一個塊。 Ruby內核中的類似方法可以在沒有塊的情況下調用並生成Enumerator。我怎樣才能做到這一點?我知道我可以使用block_given?來測試塊的存在,但我該如何繼續?我需要Fiber嗎?

順便說一句,代碼應該與Ruby 1.9.3兼容。和2.x.

回答

2

你不需要你自己的方法。您可以利用該select返回一個枚舉,如果調用時沒有一個塊的事實,所以你可以在上面巴掌with_index

p ['a','b','a','a','c'].select.with_index {|letter,index| letter == 'a' && index > 1 } 
# >> ["a", "a"] 

如果你真的想這是對陣列的方法(動態調用什麼都沒有),這是微不足道的:

class Array 
    def select_with_index(&block) 
    select.with_index(&block) 
    end 
end 

p ['a','b','a','a','c'].select_with_index {|letter,index| letter == 'a' && index > 1 } 
p ['a','b','a','a','c'].select_with_index 
# >> ["a", "a"] 
# >> #<Enumerator: #<Enumerator: ["a", "b", "a", "a", "c"]:select>:with_index> 
+0

它很難在元編程, G。 in kinda'public_send selector_name,&λ'。 – mudasobwa

+0

那麼,給這個名字吧:http://pastie.org/10786273 –

3
class Array 
    def select_with_index 
    #  ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓ this 
    return enum_for(:select_with_index) unless block_given? 
    each_with_index.select {|*args| yield(*args)}.map(&:first) 
    end 
end