请在2024年Clojure状态调查中分享您的想法!

欢迎!请参阅关于页面获取更多有关如何使用本服务的信息。

+5
Sequences

是否存在某个现有的核心函数可以用来按顺序分区列表,例如将[1 2 3 7 8 14 15 16 17 20 21 22]变成[[1 2 3] [7 8] [14 15 16 17] [20 21 22]]?

我想到了使用循环的方法来做(每次当前项和前一项的差大于1时开始一个新列表),但我怀疑是否存在一种函数式的方式来表示这种方法。

关于这个问题,这是一个简化版本的数据清洁练习,我正在尝试通过检查数据的时间戳差异来识别一个传感器数据收集中断的位置(例如断电)。我可以看到像split-with这样的函数,但我认为提供给这些函数的谓词不能提供序列中前一项的值,以便比较序列中的项。

感谢您的考虑:)

2 个回答

+4

被选中
 
最佳答案

据我所知,没有所谓的partition-when函数,它会在谓词返回true时进行分区,这在您的案例中是必需的。
建议使用reduce作为高级功能处理和底层循环之间的中间层——从某种程度上说,处理绑定到你的coll中的元素数量更为简单。

(reduce
  (fn [acc n]
    (let [prev (peek (peek acc))]
      (if (and prev (= -1 (- prev n)))
        (update acc (dec (count acc)) conj n)
        (conj acc [n]))))
  []
  [1 2 3 7 8 14 15 16 17 20 21 22])
谢谢,我觉得我还是不太习惯使用reduce来构建集合,但事后看来,使用reduce作为处理这类问题的基本工具而不降级到循环是有意义的。
+2

库dev.weavejester/medley(“一组有用的、大多数是纯函数,可能在clojure.core空间中看起来并不突兀”)自1.7.0以来包含partition-between函数。该函数可用于对有序列表进行分区。

(require '[medley.core :refer [partition-between]])

(partition-between (fn [x y] (> y (inc x))) [1 2 3 7 8 14 15 16 17 20 21 22])
;; => ((1 2 3) (7 8) (14 15 16 17) (20 21 22))
...