14

reduceアイテムを一度に処理し(reduceなど)、ある種の結果を蓄積し(reduceなど)、シーケンスの前のアイテムに基づいて処理する必要がある場合(reduceとは異なり)、ある種の拡張が必要になることがよくあります。

たとえば(ばかげたもの)、現在のアイテムと前のアイテムの両方が偶数の場合はアキュムレータに1を加算し、奇数の1つを減算します。これはばかげたケースですが、私はこの種の問題に頻繁に遭遇しました。私は通常、アキュムレータとしてベクトルを作成します。そのため、最初の項目は実際の集計であり、2番目の項目は前の項目です。これはあまりエレガントではなく、確かに冗長です。

そのような場合に役立つコア機能はありますか?そのような問題に対処するための最も慣用的な方法は何ですか?ありがとう

4

2 に答える 2

18

partition救助へ。

(reduce (fn [i [a b]]
          (cond
            (and (even? a) (even? b)) (inc i)
            (and (odd? a) (odd? b))   (dec i)
            :else i))
        0 (partition 2 1 input))

またはもう少し簡潔:

(reduce (fn [i pair]
          (condp every? pair
            even? (inc i)
            odd?  (dec i)
            i))
        0 (partition 2 1 input))
于 2012-07-20T13:23:43.643 に答える
10

この特定の問題については、パーティションを使用して前の要素を追跡する、kotarakのソリューションをお勧めします。しかし、一般的なケースでは、reduceの最終的な「答え」に加えて何らかの状態を管理する必要がある場合、ペアやマップなどを単純に縮小して、最後にアキュムレータ値を取得できます。例えば:

(defn parity [coll]
  (first (reduce (fn [[acc prev] x]
                   [(cond (and (even? prev) (even? x)) (inc acc)
                          (and (odd? prev) (odd? x)) (dec acc)
                          :else acc)
                    x])
                 [0 (first coll)], (rest coll))))
于 2012-07-20T18:09:52.663 に答える