2013-09-22 14 views
7

Mi piacerebbe capire il modo idiomatico con cui operare su raccolte di dimensioni diverse in clojure. C'è un modo in cui posso dire alla funzione 'mappa' di riempire il resto di una raccolta con qualche valore predefinito?Uso di 'map' con raccolte di dimensioni diverse nel clojure

Come esempio, supponiamo di avere 3 vettori:

(def x [1 2 3 4]) 
(def y [1 2 3 4 5]) 
(def z [1 2 3 4 5 6 7]) 

(map + x y z) ; yields (3 6 9 12) 

In questo caso, come posso pad x ed y con zeri e hanno questa resa:

(3 6 9 12 10 6 7) 

risposta

10

map non lo fa fallo da solo, ma puoi utilizzare una combinazione di concat e repeat per ottenere il risultato desiderato:

(def x [1 2 3 4]) 
(def y [1 2 3 4 5]) 
(def z [1 2 3 4 5 6 7]) 

(map + 
    (concat x (repeat 0)) 
    (concat y (repeat 0)) 
    z) ; => (3 6 9 12 10 6 7) 

Ecco la documentazione dell'API per concat e per repeat.

Ed ecco uno schizzo di come si potrebbe astrarre questo un po ', quindi non è necessario sapere quale delle collezioni è più lunga. (Nello snippet precedente, se hai concat tutte le raccolte su (repeat 0) avrai una sequenza infinita).

(defn map-longest 
    [f default & colls] 
    (lazy-seq 
    (when (some seq colls) 
    (cons 
     (apply f (map #(if (seq %) (first %) default) colls)) 
     (apply map-longest f default (map rest colls)))))) 

(map-longest + 
      0 
      [1 2 3 4] 
      [1 2 3 4 5] 
      [1 2 3 4 5 6 7]) ; => (3 6 9 12 10 6 7) 

È possibile visualizzare un paio di altri approcci come risposte a this previous question on Stack Overflow.

Problemi correlati