Объедините и проведите вычисление двух векторов, верните карту Clojure

Получилось два вектора. [обувь молочная обувь] и [1 3 1] и карта, которую я хочу получить, - {обувь 2, молоко 3}. Я пытаюсь нанести zipmap на два вектора, и показывает только {обувь 1 молоко 3}. Есть ли другой способ сделать это без цикла и итерации?

3 ответа

Решение

Вы также можете использовать для этого немного другое решение, генерируя карты с одной записью для пары элемент-сумма, а затем объединяя их с +:

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

;;=> {milk 3, shoes 2}

Вы можете сделать это с помощью reduce:

  • создавать кортежи ключ / значение из двух ваших списков
  • накапливать в карту: добавить значение к значению ключа в карте (или начать с 0, если отсутствует (передается ноль))
(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}                                                                                                                                                                     

Мне очень понравилось решение @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}
Другие вопросы по тегам