Clojure:转换为哈希映射后不是整个集合

时间:2015-03-24 02:24:06

标签: clojure hashmap

我正在探索令人兴奋的Clojure世界,但我已经停止了...... 我有两个不同长度的向量,存储在变量中。

(def lst1 ["name" "surname" "age"]) 
(def lst2 ["Jimi" "Hendrix" "28" "Sam" "Cooke" "33" "Buddy" "Holly" "23"])

我想交错它们并获得一张地图,第一个列表中的键和第二个列表中的值,如下所示:

{"name" "Jimi" , "surname" "Hendrix" , "age" "28" , 
 "name" "Sam" , "surname" "Cooke" , "age" "33" ... }

即使是以下解决方案,使用正确的密钥也可以:

{:name "Jimi" , :surname "Hendrix" , :age" "28" , ... }

我可以使用Medley库中的interleave-all函数,然后应用hash-map fn:

(apply hash-map 
    (vec (interleave-all (flatten (repeat 3 lst1)) lst2)))

=> {"age" "23", "name" "Buddy", "surname" "Holly"}

但只返回最后一位音乐家。这个持久性hashmap不是有序的,但不是重点。


我后来试图配对键和值,可能是为了将来可能使用assoc,谁知道......

(map vector
       (for [numMusicians (range 0 3) , keys (range 0 3)] (-> lst1 (nth keys) (keyword)))
       (for [values (range 0 9)] (-> lst2 (nth values) (str)))
       )

返回具有成对向量和正确关键字的延迟序列。

=> ([:name "Jimi"] [:surname "Hendrix"] [:age "28"] [:name "Sam"] ...)

现在我想尝试返回的into

  

一个新的coll,包含to-coll和from-coll的所有项目   联体。

(into {}
  (map vector
       (for [numMusicians (range 0 3) , keys (range 0 3)] (-> lst1 (nth keys) (keyword)))
       (for [values (range 0 9)] (-> lst2 (nth values) (str)))
       ))

但是又一次:

=> {:name "Buddy", :surname "Holly", :age "23"}

只是最后一位音乐家,这次是在持久阵列地图中。 我想要一张包含所有死去的音乐家的地图。有人知道我哪里错了吗?

修改:

谢谢你们!用这种方式管理了这个:

(use 'clojure.set)
(->> (partition 3 lst2) (map #(zipmap % lst1)) (map map-invert))

=> ({"name" "Jimi", "surname" "Hendrix", "age" "28"} {"name" "Sam", "surname" "Cooke", "age" "33"} {"name" "Buddy", "surname" "Holly", "age" "23"})

2 个答案:

答案 0 :(得分:1)

虽然您需要以下表格:

{"name" "Jimi" , "surname" "Hendrix" , "age" "28" , 
 "name" "Sam" , "surname" "Cooke" , "age" "33" ... }

这是不允许的,因为密钥是冲突的。您无法多次添加"name"作为密钥。密钥在地图中应该是唯一的。

但您可以使用以下代码构建地图列表:

user=> (->> (map (fn [ks vs] (interleave ks vs)) (repeat 3 lst1) (partition 3 lst2))
            (map #(apply hash-map %)))

({"age" "28", "name" "Jimi", "surname" "Hendrix"} {"age" "33", "name" "Sam", "surname" "Cooke"} {"age" "23", "name" "Buddy", "surname" "Holly"})

<强>更新 @ status203使用zipmap的解决方案看起来好多了。

user=> (->> (partition 3 lst2)
            (map #(zipmap lst1 %)))

({"age" "28", "surname" "Hendrix", "name" "Jimi"} {"age" "33", "surname" "Cooke", "name" "Sam"} {"age" "23", "surname" "Holly", "name" "Buddy"})

答案 1 :(得分:1)

每个键只能在地图中存在一次。所以你以后的值会覆盖之前的值。

要获得每个艺人的地图列表,您可以执行以下操作:

(def lst1 ["name" "surname" "age"]) 
(def lst2 ["Jimi" "Hendrix" "28" "Sam" "Cooke" "33" "Buddy" "Holly" "23"])

(->> (partition 3 lst2) ; Split out the seperate people
     (map (fn [artist-seq] (zipmap lst1 artist-seq)))) ; Use zipmap to connect the keys and values.

只要所有值都按照正确的顺序

,这应该适用于任何数量的人