10

Python には優れた機能があります。

print([j**2 for j in [2, 3, 4, 5]]) # => [4, 9, 16, 25]

Ruby ではさらに簡単です。

puts [2, 3, 4, 5].map{|j| j**2}

しかし、ネストされたループに関するものであれば、Python の方が便利に見えます。

Python では、次のことができます。

digits = [1, 2, 3]
chars = ['a', 'b', 'c']    
print([str(d)+ch for d in digits for ch in chars if d >= 2 if ch == 'a'])    
# => ['2a', '3a']

Ruby で同等のものは次のとおりです。

digits = [1, 2, 3]
chars = ['a', 'b', 'c']
list = []
digits.each do |d|
    chars.each do |ch|
        list.push d.to_s << ch if d >= 2 && ch == 'a'
    end
end
puts list

Rubyには似たようなものがありますか?

4

3 に答える 3

12

Ruby での一般的な方法は、EnumerableメソッドとArrayメソッドを適切に組み合わせて同じことを達成することです。

digits.product(chars).select{ |d, ch| d >= 2 && ch == 'a' }.map(&:join)

これは、リスト内包表記よりもわずか 4 文字ほど長く、同じように表現力があります (もちろん、リスト内包表記はリスト モナドの特別なアプリケーションにすぎないため、Ruby のコレクション メソッドを使用して適切に再構築することはおそらく可能であると主張できます)。 )、特別な構文は必要ありません。

于 2012-07-03T22:05:42.403 に答える
2

ご存じのように、Ruby にはリスト内包表記の構文糖衣がありません。そのため、想像力に富んだ方法でブロックを使用することで、より近づけることができます。人々はさまざまなアイデアを提案しています.lazylistverstehenのアプローチを見てください.どちらも条件付きのネストされた理解をサポートしています:

require 'lazylist'
list { [x, y] }.where(:x => [1, 2], :y => [3, 4]) { x+y>4 }.to_a
#=> [[1, 4], [2, 3], [2, 4]]

require 'verstehen'
list { [x, y] }.for(:x).in { [1, 2] }.for(:y).in { [3, 4] }.if { x+y>4 }.comprehend
#=> [[1, 4], [2, 3], [2, 4]]

もちろん、それは慣用的な Ruby と呼ばれるものではないため、通常は典型的な ++ アプローチを使用する方がproduct安全ですselectmap

于 2012-07-03T21:49:08.340 に答える
1

上記の RBK が示唆しているように、 Rubyのリスト内包表記は、Ruby のリスト内包表記のようなことを行うさまざまな方法を多数提供します。

ネストされたループを明示的に記述しているものはありませんが、少なくともいくつかは非常に簡単にネストできます。

たとえば、Robert Gamble が受け入れた回答では、Array#comprehend メソッドを追加することが提案されています。

class Array
  def comprehend(&block)
    return self if block.nil?
    self.collect(&block).compact
  end
end

それができたら、次のようにコードを書くことができます。

digits.comprehend{|d| chars.comprehend{|ch| d.to_s+ch if ch =='a'} if d>=2}

Python コードと比較してください。

[str(d)+ch for d in digits for ch in chars if d >= 2 if ch == 'a']

違いはごくわずかです。

  1. Ruby コードは少し長くなります。しかし、それはほとんど「理解」が綴られているという事実にすぎません。必要に応じて、いつでも短い名前にすることができます。
  2. Ruby のコードでは、順序が異なります。配列は途中ではなく最初に配置されます。しかし、考えてみれば、「すべては方法である」という哲学のために、それはまさにあなたが期待し、望んでいることです。
  3. Ruby コードでは、ネストされた内包表記のためにネストされた中括弧が必要です。これを回避して事態を悪化させない明白な方法は思いつきません ("[str,digits].comprehend2" などを呼び出したくありません)。

もちろん、ここでの Python の本当の強みは、リストを遅延評価したいと決めた場合、括弧を削除する (またはコンテキストに応じて括弧に変える) だけで、内包表記をジェネレーター式に変換できることです。しかし、そこに Array#lazycomprehend などを作成することもできます。

于 2012-07-03T21:48:30.623 に答える