Reputation: 555
So I have a list like the following:
({:name "yellowtail", :quantity 2} {:name "tuna", :quantity 1}
{:name "albacore", :quantity 1} {:quantity 1, :name "tuna"})
My goal is to search the list of map items and find duplicates keys, if there are duplicates then increment the quantity. So in the list I have two tuna mapped elements that show up. I want to remove one and just increment the quantity of the other. So the result should be:
({:name "yellowtail", :quantity 2} {:name "tuna", :quantity 2}
{:name "albacore", :quantity 1} )
With :quantity of tuna incremented to 2. I have attempted to use recur to do this without success, I'm not sure if recur is a good direction to run with. Could someone point me in the right direction?
Upvotes: 6
Views: 1982
Reputation: 13473
Why not just hold a map from name to quantity. Instead of
({:name "yellowtail", :quantity 2} {:name "tuna", :quantity 1}
{:name "albacore", :quantity 1} {:quantity 1, :name "tuna"})
... we have
{"yellowtail" 2, "tuna" 1, "albacore" 1}
We are using the map to represent a multiset. Several clojure implementations are available, but I haven't used them.
Upvotes: 0
Reputation: 2240
You can group-by
:name
your elements and then map
through the grouped collection summing the values.
Something like this
(->> your-list
(group-by :name)
(map (fn [[k v]]
{:name k :quantity (apply + (map :quantity v))})))
P.S. I assume you need to sum quantity of elements, because it's not clear what exactly you need to increment.
Upvotes: 6
Reputation: 5916
This is standard use case for map and reduce.
(->> data
(map (juxt :name :quantity identity))
(reduce (fn [m [key qty _]]
(update m key (fnil (partial + qty) 0)))
{})
(map #(hash-map :name (key %1) :quantity (val %1))))
I am using identity
to return the element in case you wish to use other properties in the map to determine uniqueness. If the map only contains two fields, then you could simplify it down to
(->> data
(mapcat #(repeat (:quantity %1) (:name %1)))
(frequencies)
(map #(hash-map :name (key %1) :quantity (val %1))))
Upvotes: 2