The current code takes a input like:
[[:k1 0] [:k1 1] [:k2 2]]
and organize the items that have the same keyword inside a list:
(([:k1 0] [:k1 1]) ([:k2 2]))
the following code works, but I feel that can be improved. The nested
map #(filter
looks ugly, I think I can use clojure for
function to produce the same result with a elegantly code.
how can I improve readability?
(defn list-of-equals [itens]
(let [get-key (fn [[k]] k)
keys (->> itens (map get-key) distinct)
pairs (map #(filter (fn [[k]]
(= % k)) itens) keys)]
pairs))
The problem you're facing is that you have to iterate over the list for every distinct key. If you were to use for
, it might look something like this.
(defn for-filter [items val]
(for [i items
:when (= (first i) (first val))]
i))
While this might be a little cleaner, using the standard library can make it more succinct. If we do a group-by operation, we can collect all the items with the same key in a single pass.
(group-by first items)
=> {:k1 [[:k1 0] [:k1 1]], :k2 [[:k2 2]]}
You can discard the keys with vals
(vals (group-by first items))
=> ([[:k1 0] [:k1 1]] [[:k2 2]])
This is a little different than your solution
(([:k1 0] [:k1 1]) ([:k2 2]))
vs
([[:k1 0] [:k1 1]] [[:k2 2]]))
If that's important:
(map #(into () %) result)
The final solution looks like:
(defn list-of-equals [items]
(->> (vals (group-by first items))
(map #(into () %))))