我需要一个类似于Array#select
的函数,但不仅将数据项传递给块,还传递给元素的索引(类似于Enumerable#each_with_index
)。我试过这个:
class Array
def select_with_index
self.each_with_index.select {|*args| yield(*args)}.map(&:first)
end
end
这似乎确实有效:
['a','b','a','a','c'].select_with_index {|letter,index| letter == 'a' && index > 1 }
结果
["a", "a"]
正如所料。但是,我不喜欢我的解决方案是,有提供一个块。可以在没有块的情况下调用Ruby核心中的类似方法,并生成Enumerator
。我怎样才能做到这一点?我知道我可以使用block_given?
来测试块的存在,但是我该如何继续呢?我需要Fiber
吗?
答案 0 :(得分: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
答案 1 :(得分: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>