Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure grouping by multiple keys

Tags:

clojure

I'm having a problem when using group-by. Here is the code

(defn combine-by-coords
  [values]
  (let [grouped-by-x (group-by :x values)]
     (persistent!
     (reduce (fn [res x-val]
               (assoc! res x-val (group-by :y (x-val grouped-by-x))))
             (transient {})
             (keys grouped-by-x)))))

Where the values of the map are of the form

{:x 754, :y 56, :someKey "zxyf" ....} .

The purpose of the code would be to group maps with the same x and y values together. First I group the x values together by using the built in group-by function, which results in

{754 [{....}, {....}]} 

After that I would group the array of the key 754 by their y value. However this is where I get an error. It doesn't seem to be possible to use the key 754. This is the error I receive:

java.lang.Integer cannot be cast to clojure.lang.IFn

I've also tried the (keyword name) function to make a key out of it but this doesn't work either.

Does anybody know a solution to this problem or perhaps knows a way to rewrite my code? In the end I would just need the maps with same x and y to be grouped together.

like image 358
wvrossem Avatar asked Jan 01 '26 05:01

wvrossem


2 Answers

You can't use numbers like keywords. You have to use get.

user=> (5 {5 :x})
#<CompilerException java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (REPL:1)>
user=> ({5 :x} 5)
:x
user=> (get {5 :x} 5)
:x

In your case: exchange (x-val grouped-by-x) with (get grouped-by-x x-val).

like image 74
kotarak Avatar answered Jan 03 '26 13:01

kotarak


Or you could get rid of the x-val (the key):

(defn combine-by-coords
  [values]
  (let [grouped-by-x (group-by :x values)]
     (persistent!
     (reduce (fn [res [x-key vals]]
               (assoc! res x-key (group-by :y vals)))
             (transient {})
             grouped-by-x))))
like image 37
Ankur Avatar answered Jan 03 '26 13:01

Ankur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!