【问题标题】:Clojure grouping by multiple keysClojure 按多个键分组
【发布时间】:2011-12-08 00:35:21
【问题描述】:

我在使用 group-by 时遇到问题。这是代码

(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 [{....}, {....}]} 

之后,我将按 y 值对键 754 的数组进行分组。然而,这是我得到一个错误的地方。似乎无法使用密钥 754。这是我收到的错误:

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

我也尝试过 (keyword name) 函数来生成一个键,但这也不起作用。

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

【问题讨论】:

    标签: clojure


    【解决方案1】:

    您不能像关键字一样使用数字。你必须使用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) 交换。

    【讨论】:

    • 啊,这更有意义 - 我想知道为什么我无法弄清楚对 group-by 的哪个调用不起作用......
    • 补充一点:注意你得到的错误:java.lang.Integer cannot be cast to clojure.lang.IFn 它告诉你你正在尝试将整数作为函数。这意味着在某些时候,一个整数被作为一个函数调用:寻找可能发生的地方:例如(5 {5 :x})) 关键字和地图实现了 clojure.lang.IFn 接口;您可以通过使用(supers (class {}))(supers (class :a)) 看到这一点,并看到整数没有:(supers (class 1))。很酷的东西,强大的工具。
    • 感谢@IsaacHodes 的额外解释。我想知道cannot be cast to clojure.lang.IFn 错误是什么意思。
    【解决方案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))))
    

    【讨论】:

      【解决方案3】:

      尝试使用#(= (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]}
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-01-27
        • 2015-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多