Frage

In clojure, I have a map that contains for each day, and each fruit, the number of fruits eaten. I would like to "reverse the hierarchy" of the map and to return the same data but with the fruits at the top of the hierarchy.

I will explain by an example:

(map-reverse-hierarchy {:monday {:banana 2 :apple 3} 
                        :tuesday {:banana 5 :orange 2}})
; => {:orange {:tuesday 2},
;     :banana {:tuesday 5, :monday 2},
;     :apple {:monday 3}}
War es hilfreich?

Lösung 2

My solution first transposes the pieces of the nested maps and then merges them all.

The pieces are transposed from {k1 {k2 v}}to {k2 {k1 v}} and then merged by apply merge-with conj

(defn map-reverse-hierarchy [mm]
   (apply merge-with conj
     (for [[k1 m] mm [k2 v] m] {k2 {k1 v}})))

Andere Tipps

You could use a list comprehension and some destructuring, like

user=> (->> (for [[day consum] data 
  #_=>            [fruit amount] consum]
  #_=>         {fruit {day amount}})
  #_=>      (apply merge-with conj))
{:orange {:tuesday 2}, :banana {:tuesday 5, :monday 2}, :apple {:monday 3}}
user=>

or using a function + mapcat instead:

(defn flip [[day consum]]
    (map (fn [[fruit amount]] {fruit {day amount}}) consum))

(apply merge-with conj (mapcat flip data))

Maybe:

(defn map-reverse-hierarchy [m]
  (let [foo (fn [a lst]
              (map #(do [(first %) {a (second %)}]) lst))
        bbb (map (fn [[a b]] (into {} (foo a b))) m)]
    (if (seq bbb)
      (apply merge-with merge bbb)
      {})))

(map-reverse-hierarchy {:monday {:banana 2 :apple 3} 
                        :tuesday {:banana 5 :orange 2}})

;{:banana {:monday 2, :tuesday 5}, :apple {:monday 3}, :orange {:tuesday 2}}

I think you'll need some custom function. Use clojure.set/map-invert[1] to swap keys and values in hash-map

[1] http://clojure.github.io/clojure/clojure.set-api.html#clojure.set/map-invert


brute-force solution:

(defn x []
  (let [i {:monday {:banana 2 :apple 3}
           :tuesday {:banana 5 :orange 2}}]
    (reduce-kv (fn [h day fruits]
                 (reduce-kv (fn [h fruit n]
                              (update-in h [fruit day] #(+ (or % 0) n))) h fruits)) {} i)))

user> (pprint (x))
{:orange {:tuesday 2},
 :banana {:tuesday 5, :monday 2},
 :apple {:monday 3}}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top