2016-04-05 86 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