2013-03-05 19 views
9

Quale sarebbe un modo più idiomatico per partizionare un seq basato su un seq di numeri interi invece di un solo intero?Partizione di un seq di interi

Ecco la mia realizzazione:

(defn partition-by-seq 
    "Return a lazy sequence of lists with a variable number of items each 
    determined by the n in ncoll. Extra values in coll are dropped." 
    [ncoll coll] 
    (let [partition-coll (mapcat #(repeat % %) ncoll)] 
    (->> coll 
     (map vector partition-coll) 
     (partition-by first) 
     (map (partial map last))))) 

Poi (partition-by-seq [2 3 6] (range)) cede ((0 1) (2 3 4) (5 6 7 8 9 10)).

risposta

3

Una variante di risposta di Ankur, con una piccola aggiunta di pigrizia e when-let invece di un test esplicito per empty?.

(defn partition-by-seq [parts coll] 
    (lazy-seq 
     (when-let [s (seq parts)] 
     (cons 
      (take (first s) coll) 
      (partition-by-seq (rest s) (nthrest coll (first s))))))) 
+0

Mi piace usare 'when-let' qui da (cons x nil) è solo (x), e trovo molto più pulito rispetto alla versione" if ". Perché usare 'nthrest' invece di' drop'? Sembra che la parte interna potrebbe essere '(when-let [n (prime parti)] (cons (prendere n coll) (partition-by-seq (parti rest) (drop n coll))))' – ToBeReplaced

+0

@ToBeReplaced' nthrest' è solo "drop" che scende avidamente, cosa che pensavo fosse appropriata in questo contesto. Ripensandoci, non sono sicuro che sia importante. In effetti, il 'primo' può essere spostato all'interno di 'when-let'. –

2
(first (reduce (fn [[r l] n] 
       [(conj r (take n l)) (drop n l)]) 
       [[] (range)] 
       [2 3 6])) 

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

'reduce' non è pigro – Ankur

+0

Man ... ridurre fa di tutto ... – ToBeReplaced

4

L'implementazione guarda bene, ma ci potrebbe essere una soluzione più semplice, che utilizza semplici ricorsione avvolto in lazy-seq (e risulta essere più efficiente) che usando la mappa e la partizione-by esistente come nel tuo caso.

(defn partition-by-seq [ncoll coll] 
    (if (empty? ncoll) 
    '() 
    (let [n (first ncoll)] 
     (cons (take n coll) 
      (lazy-seq (partition-by-seq (rest ncoll) (drop n coll))))))) 
+1

Questo potrebbe essere reso ancora più pigri prendendo' pigro-seq' fuori 'cons', in modo che anche il primo' (prendere n coll) 'non è valutato con entusiasmo. –

Problemi correlati