Clojure的;选择大小不等的列表列表中的所有第n个元素,n = 1,2,

时间:2016-11-24 09:12:08

标签: clojure

我希望有一个功能,例如,

(f '([1 4 7] [2 5 9] [3 6]))

会给出

([1 2 3] [4 5 6] [7 9])

我试过

(apply map vector '([1 4 7] [2 5 9] [3 6]))

只会产生:

([1 2 3] [4 5 6])

我发现很难描述我的要求,我很难找到一个现成的解决方案。

请帮助我改进我的描述或指向解决方案的指针。

提前致谢!

7 个答案:

答案 0 :(得分:3)

或循环/重复的方式:

user> (defn transpose-all-2 [colls]
        (loop [colls colls res []]
          (if-let [colls (seq (filter seq colls))]
            (recur (doall (map next colls)) 
                   (conj res (mapv first colls)))
            res)))
#'user/transpose-all-2

user> (transpose-all-2 x)
[[1 2 3] [4 5 6] [7 9]]

user> (transpose-all-2 '((0 1 2 3) (4 5 6 7) (8 9)))
[[0 4 8] [1 5 9] [2 6] [3 7]]

答案 1 :(得分:3)

我会解决一个更普遍的问题,这意味着您将来可能会重用该功能。我会更改map,以便它继续经过最小的地图。

(defn map-all
  "Like map but if given multiple collections will call the function f
   with as many arguments as there are elements still left."
  ([f] (map f))
  ([f coll] (map f coll))
  ([f c1 & colls]
   (let [step (fn step [cs]
                (lazy-seq
                  (let [ss (keep seq cs)]
                    (when (seq ss)
                      (cons (map first ss)
                            (step (map rest ss)))))))]
     (map #(apply f %) (step (conj colls c1))))))


(apply map-all vector '([1 4 7] [2 5 9] [3 6]))
(apply map-all vector '([1 false 7] [nil 5 9] [3 6] [8]))

注意,与许多其他解决方案相反,即使任何序列包含nilfalse,此工作也能正常工作。

答案 2 :(得分:2)

如果您提前知道向量的最大长度,则可以定义

(defn tx [colls] 
  (lazy-seq 
    (cons (filterv identity (map first colls))
          (tx (map rest colls))))) 

然后

(take 3 (tx '([1 4 7] [2 5 9] [3 6])))

答案 3 :(得分:0)

这是我自己的尝试:

(defn f [l]
  (let [max-count (apply max (map count l))
        l-patched (map (fn [e] (if (< (count e) max-count)
                                 (concat e (take (- max-count (count e)) (repeat nil)))
                                 e)) l)]
    (map (fn [x] (filter identity x)) (apply map vector l-patched))
    )) 

答案 4 :(得分:0)

这是另一个不需要事先了解矢量长度的内容:

(defn padzip [& [colls]]
    (loop [acc [] colls colls]
      (if (every? empty? colls) acc
          (recur (conj acc (filterv some? 
                                    (map first colls))) (map rest colls)))))

答案 5 :(得分:0)

一个简单的解决方案是

(defn transpose-all
  [colls]
  (lazy-seq
   (let [ss (keep seq colls)]
     (when (seq ss)
       (cons (map first ss) (transpose-all (map rest ss)))))))

例如,

(transpose-all '([1 4 7] [2 5 9] [3 6] [11 12 13 14]))
;((1 2 3 11) (4 5 6 12) (7 9 13) (14))

答案 6 :(得分:0)

另一个简单的解决方案:

(->> jagged-list
     (map #(concat % (repeat nil)))
     (apply map vector)
     (take-while (partial some identity)))

像这样的锯齿状列表

'([1   4   7     ] 
  [2   5   9     ] 
  [3   6         ] 
  [11  12  13  14]) 

将产生:

'([1   2   3   11] 
  [4   5   6   12] 
  [7   9   nil 13] 
  [nil nil nil 14])