什么时候使用`zipmap`和`map vector`?

时间:2011-05-26 08:34:14

标签: clojure

我在询问zipmap构造的特殊性,却发现我显然做错了。所以我在这个过程中学到了(map vector v u)。但在此案例之前,我曾使用zipmap来完成(map vector ...)的工作。它是否有用,因为结果地图足够小,可以整理出来?

以及实际问题:zipmap有什么用途,以及如何/何时使用它。何时使用(map vector ...)

我原来的问题需要原始订单,所以映射任何东西都不是一个好主意。但基本上 - 除了结果对的顺序 - 这两种方法是等价的,因为seq'd映射变成了一系列向量。

(for [pair (map vector v (rest v))]
  ( ... )) ;do with (first pair) and (last pair)

(for [pair (zipmap v (rest v))]
 ( ... )) ;do with (first pair) and (last pair)

4 个答案:

答案 0 :(得分:37)

当你想要从单独的键和值序列中直接构造一个hashmap 时,使用(zipmap ...)。输出是一个hashmap:

(zipmap [:k1 :k2 :k3] [10 20 40])
=> {:k3 40, :k2 20, :k1 10}

当您尝试合并多个序列时,请使用(地图矢量...)。输出是懒惰的矢量序列

(map vector [1 2 3] [4 5 6] [7 8 9])
=> ([1 4 7] [2 5 8] [3 6 9])

需要考虑的其他注意事项:

  • Zipmap仅适用于两个输入序列(键+值),而地图矢量可以处理任意数量的输入序列。如果你的输入序列是不是键值对,那么你应该使用地图矢量而不是zipmap是一个很好的暗示
  • zipmap比做地图矢量更有效,更简单,然后从键/值对创建一个散列图 - 例如(into {} (map vector [:k1 :k2 :k3] [10 20 40]))是一个非常复杂的做zipmap的方式
  • 地图向量是懒惰的 - 所以它带来了一些额外的开销,但在你真正需要懒惰的情况下非常有用(例如在处理无限序列时)
  • 你可以做(​​seq(zipmap ....))来得到一系列键值对而不是(map vector ...),但要注意这可能会重新排序键值序列对(因为中间的hashmap是无序的)

答案 1 :(得分:7)

这些方法或多或少是等同的。当您使用zipmap时,您将获得一个包含键/值对的地图。当您遍历此地图时,您将获得[键值]向量。但是没有定义地图的顺序。使用第一种方法中的“map”构造,可以创建一个包含两个元素的向量列表。订单已定义。

在您的示例中,Zipmap可能效率稍低。我会坚持使用'地图'。

修改:哦,而且zipmap不是懒惰的。所以在你的例子中不使用它的另一个原因。

编辑2 :在您真正需要地图时使用zipmap,例如快速随机基于密钥的访问。

答案 2 :(得分:3)

(zipmap k v)接受两个seq并返回map(而不是保留元素的顺序)

(map vector s1 s2 ...)获取seqs的任何计数并返回seq

当你想将两个seq压缩成地图时,请使用第一个。

当你想将向量(或列表或任何其他seq创建表单)应用于多个seq时,使用第二个。

当您打印文档的多个副本时,与“collat​​e”选项有一些相似之处:)

答案 3 :(得分:3)

两者可能看似相似但实际上却截然不同。

  • zipmap创建地图
  • (map vector ...)创建LazySeq个n元组(大小为n的向量)

这是两种截然不同的数据结构。 虽然2元组的延迟序列可能看起来与地图相似,但它们的表现却截然不同。

假设我们正在映射两个集合,coll1coll2。考虑coll1具有重复元素的情况。 zipmap的输出仅包含与coll1中重复键的最后一次出现相对应的值。 (map vector ...)的输出将包含2元组,其中包含重复键的所有值。

一个简单的REPL示例:

=> (zipmap [:k1 :k2 :k3 :k1] [1 2 3 4])
{:k3 3, :k2 2, :k1 4}

=>(map vector [:k1 :k2 :k3 :k1] [1 2 3 4])
([:k1 1] [:k2 2] [:k3 3] [:k1 4])

考虑到这一点,看到承担以下事项的危险是微不足道的:

  

但基本上 - 除了结果对的顺序 - 这两种方法是等价的,因为seq'd映射变成了一系列向量。

seq'd映射成为一系列向量,但不一定与(map vector ...)

的结果相同的向量序列

为了完整性,以下是已排序的seq'd向量:

=> (sort (seq (zipmap [:k1 :k2 :k3 :k1] [1 2 3 4])))
([:k1 4] [:k2 2] [:k3 3])

=> (sort (seq (map vector [:k1 :k2 :k3 :k1] [1 2 3 4])))
([:k1 1] [:k1 4] [:k2 2] [:k3 3])

我认为我们最接近如上所述的陈述是:

如果set本身(zip map coll1 coll2)set的结果(map vector coll1 coll2)将等于coll1结果的set

对于两个据称非常相似的操作,这是很多限定符。 这就是为什么在决定使用哪一个时必须特别小心的原因。 它们非常不同,用途不同,不能互换使用。