结合并计算两个向量 return map Clojure

Combine and do calculation two vectors return map Clojure

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

你可以用 reduce 做到这一点:

  • 从您的两个列表中构建 key/value 的元组
  • 累加到map中:将值添加到map中key的value中(如果缺失则从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}                                                                                                                                                                     

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

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

;;=> {milk 3, shoes 2}

我非常喜欢@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}