2014-10-08 12 views

risposta

13

Un altro modo per ottenere tutte le code è quello di utilizzare la funzione reductions.

user=> (def x '(1 2 3 4)) 
#'user/x 
user=> (reductions (fn [s _] (rest s)) x x) 
((1 2 3 4) (2 3 4) (3 4) (4)()) 
user=> 
1

Ecco un modo.

user=> (def x [1 2 3 4]) 
#'user/x 
user=> (map #(drop % x) (range (inc (count x)))) 
((1 2 3 4) (2 3 4) (3 4) (4)()) 
+2

questo non dovrebbe essere usato su sequenze pigre, la chiamata a contare forza l'intera sequenza – noisesmith

4

Se si vuole fare questo con le funzioni di più alto livello, penso iterate avrebbe funzionato bene qui:

(defn tails [xs] 
    (concat (take-while seq (iterate rest xs)) '(())) 

Tuttavia, credo che in questo caso sarebbe più pulito per solo scrivere con lazy-seq:

(defn tails [xs] 
    (if-not (seq xs) '(()) 
    (cons xs (lazy-seq (tails (rest xs)))))) 
+0

Grazie a ciò risulta ([1 2 3 4] (2 3 4) (3 4) (4)()) perché il primo uno è in forma vettoriale? – hariszaman

+1

@hariszaman è perché iterate restituisce prima il secondo argomento stesso senza applicare la funzione. Quindi inizia ad applicare 'rest' che restituisce un' ChunkedSeq' che stampa allo stesso modo della lista. – soulcheck

1

Un modo per farlo è

(defn tails [coll] 
    (take (inc (count coll)) (iterate rest coll))) 
+3

questo forzerà qualsiasi input pigro – noisesmith

+0

Sì, a causa del conteggio. Non ci ho pensato davvero. – turingcomplete

0
(defn tails 
    [s] 
    (cons s (if-some [r (next s)] 
      (lazy-seq (tails r)) 
      '(())))) 
+0

Che cos'è if-some? – galdre

+0

https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/if-some –

+0

Oh. Eh. Suppongo che il mio REPL sia in esecuzione 1.5. – galdre

0

Yippee! Un altro:

(defn tails [coll] 
    (if-let [s (seq coll)] 
     (cons coll (lazy-seq (tails (rest coll)))) 
     '(()))) 

questo è davvero solo quello reductions fa sotto il cofano. La migliore risposta, a proposito, è ez121sl's.