Techioz Blog

生成されたすべての要素を配列に取り込むにはどうすればよいですか?

概要

each メソッドを持つ Ruby オブジェクトがあります。ここで、生成された要素を配列にフェッチしたいと思います。私はこれをやっています:

array = []
x.each do |i|
  array << i
end

これを一行で行うことは可能でしょうか?何かのようなもの:

array = to_array(x)

Rubyにはto_arrayのような関数はありますか?自分で書くこともできますが、もしかしたらすでに存在しているのでしょうか?すべてのプロジェクトでそれが必要です。

解決策

単純な each メソッドを持つクラスを指定すると、次のようになります。

class Foo
  def each
    yield 1
    yield 2
    yield 3
  end
end

to_enum またはそのエイリアス enum_for を使用して、このようなメソッド (要素を生成するもので、名前は実際には重要ではありません) を列挙子に変えることができます。これらは、デフォルトの :each であるメソッド名を受け取ります。返された Enumerator には、to_a を提供する Enumerable が含まれます。

x = Foo.new

x.to_enum
#=> #<Enumerator: #<Foo:0x000000010e104820>:each>

x.to_enum.to_a
#=> [1, 2, 3]

Ruby の一般的なイディオムでは、ブロックが指定されていない場合、メソッド内からそのような列挙子を直接返します。

class Foo
  def each
    return to_enum(__method__) unless block_given?

    yield 1
    yield 2
    yield 3
  end
end

method は、現在のメソッドの名前をシンボルとして返します。つまり、上記のコードの :each です。

使用法:

x = Foo.new

x.each
#=> #<Enumerator: #<Foo:0x0000000120212c00>:each>

x.each.to_a
#=> [1, 2, 3]

もちろん、 to_a に限定されず、任意の Enumerator / Enumerable メソッドをこの方法で呼び出すことができます。

x.each.select(&:odd?)
#=> [1, 3]

x.each.sum
#=> 6

ブロックの動作を維持しながら:

x.each do |i|
  puts i
end
# 1
# 2
# 3
#=> nil