In Clojure Ich möchte das Ergebnis der mehrfachen Reduktion finden, während nur die Sequenz einmal konsumieren. In Java würde ich etwas tun, wie folgt aus:Führen Sie mehrere Reduzierungen in einem einzigen Durchgang in Clojure
double min = Double.MIN_VALUE;
double max = Double.MAX_VALUE;
for (Item item : items) {
double price = item.getPrice();
if (price > min) {
min = price;
}
if (price < max) {
max = price;
}
}
in Clojure I unter Verwendung Schleife viel das gleiche tun könnte und wieder auftreten, aber es ist nicht sehr zusammensetzbare - ich möchte etwas tun, die Sie hinzufügen in können andere Aggregationsfunktionen nach Bedarf
Ich habe die folgende Funktion geschrieben, dies zu tun:
(defn reduce-multi
"Given a sequence of fns and a coll, returns a vector of the result of each fn
when reduced over the coll."
[fns coll]
(let [n (count fns)
r (rest coll)
initial-v (transient (into [] (repeat n (first coll))))
fns (into [] fns)
reduction-fn
(fn [v x]
(loop [v-current v, i 0]
(let [y (nth v-current i)
f (nth fns i)
v-new (assoc! v-current i (f y x))]
(if (= i (- n 1))
v-new
(recur v-new (inc i))))))]
(persistent! (reduce reduction-fn initial-v r))))
Dies kann auf folgende Weise verwendet werden:
(reduce-multi [max min] [4 3 6 7 0 1 8 2 5 9])
=> [9 0]
Ich schätze, dass es in den meisten idiomatische Weise nicht implementiert ist, aber das Hauptproblem ist, dass es etwa 10x so langsam ist wie die Reduktionen gleichzeitig. Dies kann nützlich sein für viele, die eine Menge Reduktionen durchführen, wo die Seq schwere IO ausführt, aber das könnte sicherlich besser sein.
Gibt es etwas in einer vorhandenen Clojure-Bibliothek, die das macht, was ich will? Wenn nicht, wo liege ich in meiner Funktion falsch?
Haben Sie in Transducers gelesen? Wenn ja, sind sie verwirrend? Wenn nicht, würde es vorgeschlagen werden. –
Siehe 'juxt' unter https://github.com/cgrand/xforms –
@AWebb' juxt' scheint perfekt ... aber nicht erforderlich, oder? Mein Verständnis ist, dass Transducer eine Reihe von separaten "reduce" -Rufen ermöglichen, ohne dass Zwischensequenzen erzeugt werden, was ich zum Ziel nehme, hier zu sein. – Mars