0

我有两个向量[shoes milk shoes][1 3 1],而我想要得到的地图是{shoes 2, milk 3}。我尝试了zipmap两个向量,只{shoes 1 milk 3}显示。没有循环和迭代,还有另一种方法吗?

4

3 回答 3

7

您还可以为此采用一些不同的解决方案,为项目到金额对生成单项映射,然后将它们与以下内容合并+

(let [goods '[shoes milk shoes]
      amounts [1 3 1]]
  (apply merge-with + (map hash-map goods amounts)))

;;=> {milk 3, shoes 2}
于 2020-06-05T07:48:31.213 回答
1

我非常喜欢@leetwinski 的解决方案。

实际上,为了将来解决类似的问题,我建议首先收集列表中所有键的值 - 按它们出现的顺序:

(defn vecs2hash 
  [keys values]
  (apply merge-with concat (map (fn [k v] {k (list v)}) keys values)))

然后:

(def hm (vecs2hash '[shoes milk shoes milk] [1 4 2 3]))

hm
;; => {milk (4 3), shoes (1 2)}

然后,可以根据需要编写一个处理每个收集到的元素的函数。

定义一个新函数来总结列表中的所有值:

(defn sum-up-value
  [val]
  (apply + val))

定义一个辅助函数以应用辅助函数来处理所有值列表:

(defn apply-to-each-value
  [fun hm]
  (apply hash-map (interleave (keys hm) (map fun (vals hm)))))

所以在你的情况下:

(apply-to-each-value sum-up-values hm)
;; {milk 7, shoes 3}
于 2020-06-06T22:17:20.500 回答
1

你可以这样做reduce

  • 从您的两个列表中建立键/值元组
  • 累积到地图中:将值添加到地图中键的值(如果缺少则从0开始(传递nil))
(let [v1 '[shoes milk shoes]              
      v2 [1 3 1]] 
  (reduce                                                                 
    (fn [m [k v]]                                                   
      (update m k (fnil + 0) v))                        
    {}                     
    (map vector v1 v2)))
; → {shoes 2, milk 3}                                                                                                                                                                     
于 2020-06-05T06:55:12.423 回答