0

以前にこの答えを聞いたことがあると思ったので検索しましたが、何も見つかりませんでした。確かに、Ruby配列に関する質問はたくさんあるので、そこにあるかもしれません。

いずれにせよ、私は範囲の外積を減らして、いくつかの条件のセットを満たす外積のすべての要素の合計を返すようにしています。簡単な例を作成するには、次のような配列がある場合:

[0..1,0..1,0..1]

このセットを繰り返したいと思います。

[
  [0,0,0],
  [0,0,1],
  [0,1,0],
  [0,1,1],
  [1,0,0],
  [1,0,1],
  [1,1,0],
  [1,1,1]
]

条件""に基づいて合計を返しますreturn 1 if i[0] == 1 and i[2] == 0(これにより2が得られます)。私の考案した例では、次のように行うことができます。

br = 0..1

br.reduce(0){|sumx, x|
  sumx + br.reduce(0){|sumy, y|
    sumy + br.reduce(0){|sumz, z|
      sumz + (x == 1 and z == 0 ? 1 : 0)
    }
  }
}

、しかし実際のアプリケーションでは、範囲のセットははるかに大きくなる可能性があり、そのようにネストを減らすとかなり醜くなります。もっと良い方法はありますか?

4

1 に答える 1

3

2つの直交タスクがあります。コードがモジュール化されたままになるように、それらを混同しないようにしてください。

  1. N配列のデカルト積を作成する方法。

  2. 製品をフィルタリングしてカウントする方法。

Array#productを使用して、デカルト積を取得します。

xs = [0..1, 0..1, 0..1].map(&:to_a)
xss = xs[0].product(*xs[1..-1]) # or xs.first.product(*xs.drop(1))
#=> [[0, 0, 0], [0, 0, 1], [0, 1, 0], ..., [1, 1, 0], [1, 1, 1]]

そして今、フィルターとコーティングを行います:

xss.count { |x, y, z| x == 1 && z == 0 }
#=> 2

Array::productこれは、メソッドの代わりにclassmethodが必要になるため、少し醜いですArray#product。問題ありません。拡張モジュールに追加して、最後に次のように記述します。

Array.product(0..1, 0..1, 0..1).count { |x, y, z| x == 1 && z == 0 }
#=> 2
于 2011-02-19T14:55:58.007 に答える