Clojure拉链功能

时间:2014-09-15 18:25:44

标签: clojure standard-library sequences

我需要通过组合给定seqs的第一,第二等元素来构建seqs(vec vec)的序列。

快速搜索并查看the cheat sheet。我没有找到一个并完成了我自己的写作:

(defn zip 
  "From the sequence of sequences return a another sequence of sequenses
  where first result sequense consist of first elements of input sequences
  second element consist of second elements of input sequenses etc.

  Example:

  [[:a 0 \\a] [:b 1 \\b] [:c 2 \\c]] => ([:a :b :c] [0 1 2] [\\a \\b \\c])"
  [coll]
  (let [num-elems (count (first coll))
        inits (for [_ (range num-elems)] [])]
    (reduce (fn [cols elems] (map-indexed
                              (fn [idx coll] (conj coll (elems idx))) cols))
        inits coll)))

我感兴趣的是,有一种标准的方法吗?

2 个答案:

答案 0 :(得分:7)

(apply map vector [[:a 0 \a] [:b 1 \b] [:c 2 \c]])
;; ([:a :b :c] [0 1 2] [\a \b \c])

您可以使用map的变量arity来完成此操作。

来自map docstring:

  

...返回由应用f的结果组成的惰性序列   每个coll的第一个项的集合,然后将f应用于集合   每个coll中的 second 项目,直到任何一个colls都用完为止。   其他colls中的任何剩余项目都将被忽略....

答案 1 :(得分:0)

Kyle的解决方案很棒,我认为没有理由不使用它,但是如果你想从头开始编写这样的函数,你可以编写如下内容:

(defn zip 
  ([ret s]
    (let [a (map first s)]
      (if (every? nil? a)
        ret
        (recur (conj ret a) (map rest s)))))
  ([s]
    (reverse (zip nil s))))