【问题标题】:Obtaining max and min values in Clojure在 Clojure 中获取最大值和最小值
【发布时间】:2013-10-08 16:15:52
【问题描述】:

我正在尝试将 SQL 查询的最大和最小结果提取到 Clojure 中,以便对它们执行数学分析,但我不确定为什么会出错。

我已经在代码中使用了 max 和 min 函数来尝试确定这些结果,尽管我不断收到两个错误,这些错误似乎与我使用 :counter 关键字的方式有关。

从 SQL 查询返回到地图中的数据如下所示:

    {:date1 "20131007", :data "object1", :counter 1000}
    {:date1 "20131007", :data "object2", :counter 50}
    {:date1 "20131007", :data "object3", :counter 230}

当我使用这段代码时:

    minvalue(min(map(keyword :counter)data2))
    maxvalue(max(map(keyword :counter)data2))
    valrange(- maxvalue minvalue)
    valpc(* (/ valrange 100) 10)
    x(- maxvalue valpc)

我显然希望将 minvalue 设置为 50,并将 ma​​xvalue 设置为 1000,尽管我收到此错误:

    java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Number

如果我从代码中删除 map 函数并再次运行它,我会收到以下错误:

    java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.Number

感谢任何帮助,因为我完全陷入困境(而且我可能是 Clojure 的新手,这可能很明显)!谢谢

【问题讨论】:

  • 关于性能的说明:如果您有大量的地图要处理,使用reduce(类似(reduce min (:counter (first maps)) (map :counter (rest maps))))将比apply 更有效。

标签: clojure max min


【解决方案1】:

对您的代码进行一些更改:

  • min 和 max 采用可变数量的参数,而不是一个集合。使用 apply to,将集合的内容应用为参数。
  • Clojure 命名约定使用 - 单词之间
  • 有效的调用必须是一种形式(基本上是第一项可调用的列表)
  • 无需使用“关键字”,关键字用于当您有字符串并需要关联关键字时。为了将数据拖出地图,关键字本身充当函数,例如 (:a {:a 1 :b 2}) 返回 1。
  • 排除了前两行中的共性

    (def data [{:date1 "20131007", :data "object1", :counter 1000}
               {:date1 "20131007", :data "object2", :counter 50}
               {:date1 "20131007", :data "object3", :counter 230}])
    
    (def counters (map :counter data))      ; => (100 50 230)
    (def min-value (apply min counters))    ; => 50
    (def max-value (apply max counters))    ; => 1000
    (def val-range (- max-value min-value)) ; => 950
    (def val-pc (* (/ val-range 100) 10))   ; => 95
    (def x (- max-value val-pc))            ; => 905
    

【讨论】:

    【解决方案2】:
    user=> data
    [{:data "object1", :date1 "20131007", :counter 1000} {:data "object2", :date1 "20131007", :counter 50} {:data "object3", :date1 "20131007", :counter 230}]
    
    user=> (apply max-key :counter data)
    {:data "object1", :date1 "20131007", :counter 1000}
    
    user=> (apply min-key :counter data)
    {:data "object2", :date1 "20131007", :counter 50}
    

    【讨论】:

    • 谢谢,我刚刚尝试了上面的代码,但仍然出现错误:java.lang.ClassCastException: clojure.lang.LazySeq 无法转换为 java.lang.Number。我只是从 :counter 键中寻找要返回的实际整数值,以便我可以使用实际值。再次感谢您的帮助!
    • 如果您只想要值,请使用(apply min (map :counter data))(reduce min (map :counter data))。上面的代码和此代码有效。 data 应该是地图向量。
    猜你喜欢
    • 1970-01-01
    • 2021-11-08
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    相关资源
    最近更新 更多