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

独自の方法は必要ありません。あなた本当には、動的呼び出しのために(これはアレイ上のメソッドになりたい場合は

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

:あなたはブロックせずに呼び出された場合、あなただけの上にwith_indexを平手打ちすることができますのでselectは、列挙子を返しているという事実を活用することができますこれはほんの少しです:

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。 '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 
関連する問題