Rekursiv reverse Sequenz in Clojure
Will ich das umkehren einer Reihenfolge, in Clojure ohne die reverse
Funktion, und dies rekursiv.
Hier ist was ich kam mit:
(defn reverse-recursively [coll]
(loop [r (rest coll)
acc (conj () (first coll))]
(if (= (count r) 0)
acc
(recur (rest r) (conj acc (first r))))))
Beispiel-Ausgabe:
user> (reverse-recursively '(1 2 3 4 5 6))
(6 5 4 3 2 1)
user> (reverse-recursively [1 2 3 4 5 6])
(6 5 4 3 2 1)
user> (reverse-recursively {:a 1 :b 2 :c 3})
([:c 3] [:b 2] [:a 1])
Fragen:
- Gibt es einen kürzeren Weg, dies zu tun, d.h. ohne Schleife/wiederholen?
- Gibt es eine Möglichkeit, dies zu tun, ohne mit einem "Akkumulator" - parameter in der Schleife?
Referenzen:
Was ist der beste Weg, um rekursiv reverse a string in Java?
http://groups.google.com/group/clojure/browse_thread/thread/4e7a4bfb0d71a508?pli=1
- Waren Sie möglicherweise versucht, diese 4clojure problem? 🙂
- Nein, ich war es nicht. "Reverse a string rekursiv" ist eine sehr häufige interview problem.
Du musst angemeldet sein, um einen Kommentar abzugeben.
acc
, da die ursprüngliche Eingabe kann leer sein (und es ist mehr code).Als für
loop
/recur
und dieacc
müssen Sie einige Weg, vorbei an rund um die Arbeits-Umgekehrt-Liste. Es ist entwederloop
, oder fügen Sie einen anderen Parameter an die Funktion (die ist wirklich, wasloop
tut sowieso).Oder eine höhere Ordnung Funktion:
(source reverse)
Clojure> (reverse-recursively {:a 1 :b 2})
java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap
(seq coll)
, statt nurcoll
.(reverse-recursively ())
zurück(nil)
. Dieses problem wird auch gelöst durch die Verwendung(seq coll)
, obwohl ich es lieber nicht destructure in derloop
(das stellt eine ziemlich nutzlose:as
), sondern um eineif-let
innerhalb der Schleife.:as all
ist notwendig zu prüfen, die abschließende Bedingung, ohne die Einführung der null/false-as-element Probleme. Edit: nvm, ich habe herausgefunden, was du gemeint hast. Normalerweise mache ich das auch, aber ich habe auf ein destructuring kick in letzter Zeit.Frage 1 mit ja beantwortet, das ist, was ich kam mit meiner Antwort auf die Rekursion koan (ich könnte nicht sagen, ob es gut war clojure praktizieren oder nicht).
(recursive-reverse (apply str (seq (take 100000 (repeat "foo")))))
Zuliebe exhaustivenes, es gibt eine weitere Methode mit
into
. Da in intern verwendetconj
es kann wie folgt verwendet werden :In der aktuellen version von Clojure gibt es eine eingebaute Funktion, die aufgerufen wird
rseq
. Für jeden, der vorbeifährt.rseq
erfordert die Eingabe-SequenzReversible
, das es generell ungeeignet (nicht mitcons
Listen, mitPersistentList
mitLazySeq
mit Saiten). Es ist gedacht als eine Optimierung für Sequenzen, die rückgängig gemacht werden können, in konstanter Zeit.Q1.
Die JVM kann keine Optimierung der Rekursion eine rekursive Funktion, die würden direkt und stack overflow. Daher, Clojure, die die loop/recur. Also, ohne Verwendung einer Funktion, die sich wiederholen Tiefe der Rekursion können nicht definiert werden. (das wird auch intern verwendet, um wiederholt als eine Funktion Trampolin.)
Q2.
einer rekursiven Funktion durch wiederkehren, muss tail-rekursiv. Wenn der normale rekursive Funktion änderung tail-rekursive Funktion, so dass es notwendig ist, zu tragen über der Wert einer Variablen ist notwendig, da der Akku.
PersistentArrayMap
Clojure ist ungeordnet wiejava.util.HashMap
? Das ist nicht intuitiv.