3

Python と Ruby の両方で値を生成する関数からリストを作成するエレガントな方法を考え出そうとしています。

Python の場合:

def foo(x):
    for i in range(x):
        if bar(i): yield i 
result = list(foo(100))

ルビーの場合:

def foo(x)
  x.times {|i| yield i if bar(i)}
end
result = []
foo(100) {|x| result << x}

私は両方の言語で作業するのが大好きですが、Ruby バージョンではリストを初期化してから入力する必要があることにいつも少し悩まされていました。Python のyield結果は単純な反復であり、これは素晴らしいことです。Rubyyieldはブロックを呼び出します。これも優れていますが、リストを埋めたいだけの場合は、ちょっとぎこちなく感じます。

よりエレガントな Ruby の方法はありますか?

UPDATE関数から得られる値の数が必ずしも x に等しいとは限らないことを示すために、例を作り直しました。

4

7 に答える 7

5

Pythonコード(Rubyジェネレーターを使用)とまったく同じものは次のようになります。

def foo(x)
    Enumerator.new do |yielder|
        (0..x).each { |v| yielder.yield(v) if bar(v) }
    end
end

result = Array(foo(100))

上記では、リストは遅延生成されます(Pythonの例と同じように)。見る:

def bar(v); v % 2 == 0; end

f = foo(100)
f.next #=> 0
f.next #=> 2
于 2010-09-23T17:58:46.580 に答える
1

stbutonによって投稿されたPythonリスト内包バージョンでは、ジェネレーターが必要な場合は、範囲ではなくxrangeを使用してください。rangeは、リスト全体をメモリに作成します。

于 2009-03-04T14:21:07.327 に答える
1

それはまさにあなたが探していたものではないことはわかっていますが、ルビーで例を表現するよりエレガントな方法は次のとおりです。

result = Array.new(100) {|x| x*x}
于 2009-03-04T01:46:43.553 に答える
1
def squares(x)
  (0..x).map { |i| i * i }
end

times値の範囲を含むものはすべて、配列生成ではなく、範囲で処理するのが最適です。

于 2009-03-04T01:47:00.510 に答える
1

yieldruby と python では意味が異なります。私の記憶が正しければ、Ruby ではコールバック ブロックを指定する必要がありますが、Python のジェネレーターは渡され、それを保持する人に譲ることができます。

于 2009-03-04T14:34:17.890 に答える