在 Clojure Core 或 Contrib 中是否有相应的 Zip 函数?

在 Clojure 中,我想组合两个列表来得到一个对列表,

> (zip '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))

在哈斯克尔或 Ruby 中,这个函数被称为 什么都没有。实现它并不困难,但是我想确保我没有遗漏 Core 或 Contrib 中的一个函数。

Core 中有一个 什么都没有名称空间,但它是 描述,用于提供对 Zipper 功能技术的访问,这似乎不是我想要的。

在 Core 中是否有一个等效的函数来组合2个或更多的列表?

如果没有,是否是因为有一种惯用方法使得该函数不再需要?

33865 次浏览
(map vector '(1 2 3) '(4 5 6))

做你想做的事:

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

Haskell 需要一个 zipWith(zipWith3zipWith4,...)函数的集合,因为它们都需要具有特定的 类型; 特别是,它们接受的输入列表的数量需要固定。(zipzip2zip3,... 家族可以被看作是 zipWith家族的一个专门化,用于常见的元组管用例)。

相比之下,Clojure 和其他 Lisps 对可变数量函数有很好的支持; map就是其中之一,它可以用类似于 Haskell 的方式来实现“元组”

zipWith (\x y -> (x, y))

在 Clojure,构建“ tuple”的惯用方法是构建一个短向量,如上所示。

(为了完整起见,请注意带有一些基本扩展的 Haskell 确实允许可变元素函数; 但是,使用它们需要对语言有很好的理解,而普通的 Haskell 98可能根本不支持它们,因此固定元素函数对于标准库来说是更好的选择

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

为了得到您想要的结果,在两个列表之间映射 list将得到一个列表列表,如示例所示。我认为许多克洛朱里亚人会倾向于使用矢量,尽管它适用于任何东西。并且输入不需要是相同的类型。Map 从它们创建 seqs,然后映射 seqs,因此任何 seq‘ able 输入都可以正常工作。

(map list '(1 2 3) '(4 5 6))
(map list  [1 2 3] '(4 5 6))
(map hash-map  '(1 2 3) '(4 5 6))
(map hash-set  '(1 2 3) '(4 5 6))

内置的方式就是函数“交错”:

(interleave [1 2 3 4] [5 6 7 8]) => [1 5 2 6 3 7 4 8]
(partition 2 (interleave '(1 2 3) '(4 5 6)))
=> ((1 4) (2 5) (3 6))

或者更一般地说

(defn zip [& colls]
(partition (count colls) (apply interleave colls)))


(zip '( 1 2 3) '(4 5 6))           ;=> ((1 4) (2 5) (3 6))


(zip '( 1 2 3) '(4 5 6) '(2 4 8))  ;=> ((1 4 2) (2 5 4) (3 6 8))

# (application map list%)像 Python zip * 函数一样转换矩阵。作为一个宏定义:

User = > (defMacropy-zip [ lst ]’(application map list ~ lst))

#’user/py-zip

User = > (py-zip’((1234)(9999)(5678)))

((195)(296)(397)(498))

User = > (py-zip’((195)(296)(397)(498)))

((1234)(9999)(5678))

有一个叫做 zipmap 的函数可能有类似的效果, (zipmap (1 2 3)(456)) 产出是流动的: {36,25,14}