Закрытая группировка по нескольким ключам - PullRequest
2 голосов
/ 07 декабря 2011

У меня проблема при использовании группировки.Вот код

(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)))))

Там, где значения карты имеют вид

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

Целью кода было бы объединить карты с одинаковыми значениями x и y вместе,Сначала я группирую значения x вместе, используя встроенную функцию group-by, что приводит к

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

После этого я сгруппирую массив ключа 754 по их значению y.Однако здесь я получаю ошибку.Кажется, невозможно использовать ключ 754. Я получаю сообщение об ошибке:

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

Я также пробовал использовать функцию (имя ключевого слова), чтобы сделать из нее ключ, но этотоже не работает.

Кто-нибудь знает решение этой проблемы или, возможно, знает способ переписать мой код?В конце мне просто нужно, чтобы карты с одинаковыми x и y были сгруппированы вместе.

Ответы [ 3 ]

4 голосов
/ 07 декабря 2011

Вы не можете использовать числа как ключевые слова. Вы должны использовать 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

В вашем случае: обмен (x-val grouped-by-x) на (get grouped-by-x x-val).

2 голосов
/ 07 декабря 2011

Или вы можете избавиться от x-val (ключ):

(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))))
0 голосов
/ 07 декабря 2011

Попробуйте использовать #(= (key %) 754) вместо 754 в качестве первого аргумента для group-by.

Проблема в том, что первым аргументом group-by должна быть функция, которая возвращает true для значений, которые вы хотите сгруппировать. Ключевые слова могут использоваться в качестве функций, поэтому они работают нормально, но, конечно, целое число не является функцией, поэтому нам нужно написать функцию, которая выполняет сравнение.

Обратите внимание, что это обеспечивает большую гибкость, например,

Clojure> (group-by even? (range 10))
{true [0 2 4 6 8], false [1 3 5 7 9]}

ОБНОВЛЕНИЕ: Похоже, что проблема не в рассматриваемом коде, но я решил оставить этот ответ на случай, если у кого-то возникнет аналогичная проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...