【发布时间】:2014-04-21 23:02:44
【问题描述】:
我想将一个序列“分块”成与 partition-by 相同的子序列,只是该函数不是应用于每个单独的元素,而是应用于一系列元素。
所以,例如:
(gather (fn [a b] (> (- b a) 2))
[1 4 5 8 9 10 15 20 21])
会导致:
[[1] [4 5] [8 9 10] [15] [20 21]]
同样:
(defn f [a b] (> (- b a) 2))
(gather f [1 2 3 4]) ;; => [[1 2 3] [4]]
(gather f [1 2 3 4 5 6 7 8 9]) ;; => [[1 2 3] [4 5 6] [7 8 9]]
我的想法是我将列表的开头和下一个元素应用于函数,如果函数返回 true,我们将列表的当前头部分区到该点到一个新的分区中。
我写过这个:
(defn gather
[pred? lst]
(loop [acc [] cur [] l lst]
(let [a (first cur)
b (first l)
nxt (conj cur b)
rst (rest l)]
(cond
(empty? l) (conj acc cur)
(empty? cur) (recur acc nxt rst)
((complement pred?) a b) (recur acc nxt rst)
:else (recur (conj acc cur) [b] rst)))))
它有效,但我知道有一种更简单的方法。我的问题是:
是否有内置函数可以在不需要该函数的情况下执行此操作?如果没有,是否有我忽略的更惯用(或更简单)的解决方案?结合 reduce 和 take-while 的东西?
谢谢。
【问题讨论】:
-
这种问题,我一看到也想到了一个很长的解决方案,但我知道clojure专家会用大约2行代码解决它
标签: clojure