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

Clojure: not the whole collection after conversion to hash map

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

(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 函数,然后应用哈希映射 fn:

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

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

但 return 只是最后一位音乐家。此持久性哈希图未排序,但不是重点。


我后来尝试将键和值配对,也许是为了将来可能使用 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)))
       )

Returns 具有成对向量和适当关键字的惰性序列。

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

现在我想尝试 into 应该 return

a new coll consisting of to-coll with ALL of the items of from-coll conjoined.

(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"}

只是最后一位音乐家,这次是在持久数组映射中。 我想要一张地图,上面有我所有死去的音乐家。有人知道我哪里错了吗?

编辑:

谢谢大家!以这种方式管理 fn:

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

尽管您想要以下形式:

{"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"})

每个键在映射中只能存在一次。所以你后面的值会覆盖前面的值。

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

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

只要所有值都以正确的顺序存在,这应该适用于任何数量的人