Clojure按多个键分组

时间:2011-12-07 15:00:20

标签: clojure

使用分组时我遇到了问题。这是代码

(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值的地图分组在一起。首先,我使用内置的group-by函数将x值组合在一起,结果为

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

之后,我会将键754的数组按其y值分组。然而,这是我收到错误的地方。似乎不可能使用密钥754.这是我收到的错误:

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

我也尝试过(关键字名称)函数来创建一个密钥,但这也不起作用。

有人知道这个问题的解决方案,或者知道重写代码的方法吗?最后,我只需要将具有相同x和y的地图组合在一起。

3 个答案:

答案 0 :(得分:4)

您不能使用关键字之类的数字。您必须使用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)

答案 1 :(得分:2)

或者你可以摆脱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))))

答案 2 :(得分:0)

尝试使用#(= (key %) 754)而不是754作为group-by的第一个参数。

问题是分组依据的第一个参数需要是一个函数,该函数对要分组的值返回true。关键字可以用作函数,因此这些工作正常,但当然整数不是函数,所以我们需要编写一个进行比较的函数。

请注意,这允许很多灵活性,例如

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

更新:似乎这不是问题代码的问题,但我会留下这个答案,万一有人遇到类似的问题。