2013-09-22 20 views
7

Chciałbym zrozumieć idiomatyczny sposób, w jaki można operować kolekcjami różnej wielkości w clojure. Czy istnieje sposób, w jaki mogę określić funkcję "map", aby umieścić resztę kolekcji z pewną wartością domyślną?Używanie "mapy" z kolekcjami o różnej wielkości w clojure

Jako przykład, przypuśćmy, że ma 3 wektory:

(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) 

W tym przypadku, jak można podkładka X i Y zerami i mają tę wydajność:

(3 6 9 12 10 6 7) 

Odpowiedz

10

map nie Zrób to sam, ale możesz użyć kombinacji concat i repeat, aby uzyskać pożądany wynik:

(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) 

Oto dokumentacja API dla concat i dla repeat.

A oto szkic, w jaki sposób można to trochę streścić, więc nie trzeba wiedzieć, która z kolekcji jest najdłuższa. (W powyższym fragmencie, jeśli concat wszystkie kolekcje do (repeat 0) będziesz miał nieskończoną sekwencję).

(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) 

Możesz zobaczyć kilka innych podejść jako odpowiedzi na this previous question on Stack Overflow.