clojure эквивалент python defaultdict

#python #clojure #defaultdict

#python #clojure #defaultdict

Вопрос:

предполагая, что у нас есть некоторая функция f, которая возвращает значение, которое может быть использовано в качестве ключа dict:

 d = defaultdict(set)

for x in xs:
    d[f(x)].add(x)
  

Структура, вероятно, будет выглядеть примерно так, но я не могу понять, как а) предоставить значение по умолчанию и б) объединить с существующим значением

 (defn build-maps [xs]
  (let [inverse-map {}]
    (reduce (fn [im x]
              (let [y (f x)
                    im' (assoc im y x)] ; want to add x to a set
                im')) inverse-map xs)))
  

обновление, похоже, работает следующее

 (defn build-maps [xs]
  (let [inverse-map {}]
    (reduce (fn [im x]
              (let [y (f x)
                    new-im (assoc im y (set/union (im y) #{x}))]
                new-im)) inverse-map xs)))
  

Ответ №1:

Я бы написал это так:

 (apply merge-with into
       (for [x xs]
         {(f x) #{x}}))
  

Но если вам нужно что-то более близкое к вашему плану, основанному на сокращении, вы могли бы написать:

 (reduce (fn [m x]
          (update m (f x) (fnil conj #{}) x))
        {}, xs)
  

Комментарии:

1. Причина подхода reduce заключается в том, что я фактически обновляю два словаря одновременно