Clojure Core或Contrib中的Zip函数是否等效?


130

在Clojure中,我想合并两个列表以给出成对列表,

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

在Haskell或Ruby中,该函数称为zip。实现它并不困难,但是我想确保我不会错过Core或Contrib中的一个函数。

Core中有一个zip名称空间,但是它被描述为提供对Zipper功能技术的访问,这似乎不是我想要的。

在Core中,是否有等效功能可以通过这种方式组合2个或更多列表?

如果没有,是否是因为存在一种惯用方法导致不需要此功能?


Answers:


220
(map vector '(1 2 3) '(4 5 6))

做你想要的:

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

Haskell需要zipWithzipWith3,,zipWith4...)函数的集合,因为它们都必须是特定的类型;特别是,他们接受的输入列表的数量需要固定。(本zipzip2zip3,...系列可以看作是一个专业化zipWith的家人几倍的常见的情况)。

相反,Clojure和其他Lisps对可变arity函数具有良好的支持;map是其中之一,可以类似于Haskell的方式用于“打结”

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

如上所示,在Clojure中构建“元组”的惯用方式是构造一个短向量。

(为完整起见,请注意具有某些基本扩展的Haskell确实允许使用可变arity函数;但是使用它们需要对语言有很好的了解,而普通的Haskell 98可能根本不支持它们,因此固定arity函数是可取的用于标准库。)


8
请注意,这zip与集合长度不同时的行为不同。Ruby将继续处理并nil为较短的集合提供,而Clojure将在其中一个集合用完后停止处理。
Nate W.

@NateW。请注意,谢谢。在这方面,Haskell的zip行为类似于Clojure的行为map
米哈尔Marczyk

1
请问有关可变arity Haskell函数的参考吗?
Teodor

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


11

为了给您确切的所需,list在两个列表之间进行映射将为您提供一个列表列表,如您的示例所示。我认为许多Clojurian都倾向于为此使用向量,尽管它可以与任何东西一起使用。输入的类型不必相同。map从它们创建序列,然后映射这些序列,以便任何可序列化的输入都能正常工作。

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

1
我认为您的意思是哈希映射和哈希集,而不是映射和集。
cgrand

3

内置方式将只是函数“ interleave”:

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

6
要实现OP的目标,您应该添加(partition 2 (interleave [1 2 3 4][5 6 7 8]))
skuro 2012年

是的-似乎我没有仔细查看OP的期望输出。
lsh 2012年

-1

有一个名为zipmap的函数,可能具有相似的效果,(zipmap (1 2 3)(4 5 6))输出如下所示:{3 6,2 5,1 4}


zipmap会向您返回一张地图,该地图不保证顺序
Ilya Shinkarenko 2015年

-2

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

用户=>(defmacro py-zip [lst]`(应用地图列表〜lst))

#'user / py-zip

user =>(py-zip'(((1 2 3 4)(9 9 9 9)(5 6 7 8))))

(((1 9 5)(2 9 6)(3 9 7)(4 9 8))

用户=>(py-zip'(((1 9 5)(2 9 6)(3 9 7)(4 9 8)))

((1 2 3 4)(9 9 9 9)(5 6 7 8))


这比仅使用“地图”更好吗?宏在这里有什么意义?
戴夫牛顿
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.