【问题标题】:How to use reduce and into properly如何正确使用 reduce 和 into
【发布时间】:2017-12-22 16:35:23
【问题描述】:

我正在学习 Clojure,实际上我正在做一些练习来练习,但我遇到了一个问题:

我需要创建一个sum-consecutives 函数,它将数组中的连续元素相加,从而产生一个新元素,例如:

[1,4,4,4,0,4,3,3,1]  ; should return [1,12,0,4,6,1]

我做了这个应该可以正常工作的功能:

(defn sum-consecutives [a]
  (reduce #(into %1 (apply + %2)) [] (partition-by identity a)))

但是它会抛出一个错误:

IllegalArgumentException 不知道如何创建 ISeq: java.lang.Long clojure.lang.RT.seqFrom (RT.java:542)

谁能帮我看看我的功能有什么问题?我已经在网上搜索过这个错误,但没有找到有用的解决方案。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    您可能希望使用conj 而不是into,因为into 期望它的第二个参数是seq

    (defn sum-consecutives [a]
      (reduce 
        #(conj %1 (apply + %2))
        [] 
        (partition-by identity a)))
    
    (sum-consecutives [1,4,4,4,0,4,3,3,1]) ;; [1 12 0 4 6 1]
    

    或者,如果您真的想要使用into,您可以将您对apply + 的调用包装在一个向量字面量中,如下所示:

    (defn sum-consecutives [a]
      (reduce 
        #(into %1 [(apply + %2)])
        [] 
        (partition-by identity a)))
    

    【讨论】:

    • 您的 conj 分辨率运行良好,准确地显示了我所缺少的内容。我将深入研究这些功能。谢谢你的帮助
    【解决方案2】:

    您的方法从partition-by 开始是合理的。但是让我们 通过这些步骤来总结它产生的每个子序列。

    (let [xs [1 4 4 4 0 4 3 3 1]]
      (partition-by identity xs))  ;=> ((1) (4 4 4) (0) (4) (3 3) (1))
    

    要得到一个总和,你可以使用reduce(虽然是一个简单的apply 而是would also work 这里);例如:

    (reduce + [4 4 4])  ;=> 12
    

    现在把上面的每个子序列都放在reducemap

    (let [xs [1 4 4 4 0 4 3 3 1]]
      (map #(reduce + %) (partition-by identity xs)))  ;=> (1 12 0 4 6 1)
    

    一些注意事项...

    我正在使用 xs 来表示您的矢量(如 Clojure Style Guide)。

    let 有时是一种方便的形式,用于试验一些 建立最终功能的数据。

    逗号不是必需的,而且通常会分散注意力,除了偶尔 使用哈希映射。

    因此,基于所有这些的最终函数可能类似于:

    (defn sum-consecutives [coll]
      (map #(reduce + %) (partition-by identity coll)))
    

    【讨论】:

    • 感谢您的解决方案和提示。我会为他们工作
    猜你喜欢
    • 2020-05-21
    • 2020-09-18
    • 2016-12-03
    • 2019-04-08
    • 1970-01-01
    • 2013-09-01
    • 2021-01-26
    • 2017-03-08
    • 2020-06-19
    相关资源
    最近更新 更多