2016-03-24 9 views
1

Ich versuche, eine Methode zu finden, um Partition (mit [] Padding) in Clojure zu implementieren. Ich denke, es ist machbar Schleife und wieder auftreten und in die Liste Abbildung:Erneutes Implementieren der Partition in clojure

(defn collect-h [v n] 
    (loop [i n 
      res [] 
      lst v 
      ] 
    (if (= 0 i) 
     res 
     (recur (dec i) (cons (first lst) res) (next lst)) 
     ) 
    ) 
    ) 

Das Problem ist also, dass die Umsetzung funktioniert nur auf der ersten Reihe der Antwort „(collect-h [1 2 3 4 5 6 7 8 9 10] 3) wird ((1 2 3)) geben“. Also muss ich es der ganzen Sammlung zuordnen und die erste n Nummer in jeder Schleife entfernen, aber das sieht nicht wirklich effizient aus. Ich frage mich, ob es einen besseren Weg gibt, es zu lösen.

Edit:

so sollte es so funktionieren:

(collect-h [1 2 3 4 5 6 7 8 9 10] 3)     ;; ((1 2 3) (4 5 6) (7 8 9) (10)) 

, die gleiche ist

(partition 3 3 [] [1 2 3 4 5 6 7 8 9 10]) 
+0

Können Sie ein Beispiel für es zu benutzen? Genauer gesagt, was Sie hineinlegen wollen und was Sie wollen, dass es zurückkehrt. – Mike

+0

@Mike mein schlechtes. Ich habe die Frage bearbeitet. – Yar

+1

Es gibt eine Kernfunktion 'partition-all', die genau das zu tun scheint, was Sie wollen ... versuchen Sie es zu implementieren? Blick auf den Quellcode? https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L6947 –

Antwort

2

Wie wäre das?

(defn partition-ghetto [n xs] 
    (if (seq xs) 
    (cons (take n xs) (partition-ghetto n (drop n xs))) 
    ())) 

(partition-ghetto 3 (range 10)) 
=> ((0 1 2) (3 4 5) (6 7 8) (9)) 

Definitiv nicht so gut wie die Kernversion, aber könnte einige Ideen zur Verfügung stellen?

Beachten Sie, dass diese rekursive Definition nicht tail rekursiv ist, so wird der Stapel für große Sequenzen blasen, noch ist es faul wie die meisten Clojure Sequenzfunktionen. Der Vorteil der Faulheit bei Sequenzen ist, dass Sie weder stapel- noch haufengebunden sind, wenn Sie in einem Stream arbeiten. Unten finden Sie alternative Antworten, die Lösungen für diese Probleme bieten.

+0

Das ist eine sehr clevere, einfache Lösung. Danke Timothy. – Yar

+0

aber es ist nicht Schwanz rekursiv! '(Partition-Ghetto 10 (Bereich 1000000))' => CompilerException java.lang.StackOverflowError, Kompilierung: (form-init7979654044074214656.clj: 875: 28) – leetwinski

+0

@Hooman - Vielen Dank, froh, dass es geholfen hat. @ Leetwinski Und es ist auch nicht faul! :) Ein "Lazy-Seq" zu werfen wäre eine gute Verbesserung. –

5

@ Timothy-Pratley Antwort ist nett, aber es ist nicht Schwanz rekursiv, was bedeutet, dass es im Falle einer großen Sammlung Stapelüberlauf verursachen würde. Hier wird nicht Stapel raubend Variante:

(defn my-partition [n items] 
    (loop [res [] items items] 
    (if (empty? items) 
     res 
     (recur (conj res (take n items)) 
      (drop n items))))) 

user> (my-partition 3 (range 10)) 
[(0 1 2) (3 4 5) (6 7 8) (9)] 
3

Gebäude aus @ Timothy-Pratley und Clojure Quellcode, können Sie auch faul-Seq verwenden:

(defn partition-ghetto [n xs] 
    (lazy-seq (when-let [s (seq xs)] 
       (cons (take n s) (partition-ghetto n (drop n s)))))) 
+0

Whoops, ich habe deine Antwort blindlings kopiert, anstatt die Referenz zu aktualisieren. Ich habe es jetzt korrigiert. – Mike

+0

Schön! Ich mag besonders, dass diese Version so prägnant ist. Sehr elegant und mehr Clojury. –

Verwandte Themen