Clojure 元素每次出现后分割向量
这应该很容易,但我发现比预期的更难 给定Clojure 元素每次出现后分割向量,clojure,Clojure,这应该很容易,但我发现比预期的更难 给定[0 1 2 0 1 2 0 1],在每次发生2后拆分序列 结果应类似于[[0 1 2][0 1 2][0 1]] split函数仅在第一次执行时分割。我的想象力也局限于如何使用分区函数来实现这一点。这里有一种方法,将两个分区变体组合起来。首先使用partitionby在2的实例上进行划分,然后使用partitionall获取两个和两个分区,并使用concat将它们连接在一起 (->> [0 1 2 0 1 2 0 1] (parti
[0 1 2 0 1 2 0 1]
,在每次发生2
后拆分序列
结果应类似于[[0 1 2][0 1 2][0 1]]
split
函数仅在第一次执行时分割。我的想象力也局限于如何使用分区
函数来实现这一点。这里有一种方法,将两个分区
变体组合起来。首先使用partitionby
在2的实例上进行划分,然后使用partitionall
获取两个和两个分区,并使用concat
将它们连接在一起
(->> [0 1 2 0 1 2 0 1]
(partition-by (partial = 2)) ;;((0 1) (2) (0 1) (2) (0 1))
(partition-all 2) ;;(((0 1) (2)) ((0 1) (2)) ((0 1)))
(mapv (comp vec (partial reduce concat)))) ;;[[0 1 2] [0 1 2] [0 1]]
尽管注意,如果输入从2开始,返回的分区也将从2开始,而不是像这里那样结束 在这里,所有输入都按要求工作:
(reduce #(let [last-v (peek %1)]
(if (= 2 (last last-v))
(conj %1 [%2])
(conj (pop %1) (conj last-v %2))))
[[]]
[2 2 0 1 2 3 4 2 2 0 1 2 2])
=> [[2] [2] [0 1 2] [3 4 2] [2] [0 1 2] [2]]
尽管Magos有一个优雅的解决方案,但不幸的是,正如他所提到的,它并不完整。因此,上面的工作应该使用reduce
来完成
我们看一下最近添加的元素。如果是2
,我们将创建一个新的子向量((conj%1[%2])
)。否则,我们将其添加到最后一个子向量。真的很简单。现有的函数,如分区
s和拆分
s,在可能的情况下可以很好地重用,但有时最好的解决方案是自定义函数,在这种情况下,它实际上非常干净。以前的解决方案是可以的(尽管@magos solution在某些情况下有缺陷),但如果将此函数用作实用程序(我想这是相当普遍的),我会使用经典的迭代方法:
(defn group-loop [delim coll]
(loop [res [] curr [] coll (seq coll)]
(if coll
(let [group (conj curr (first coll))]
(if (= delim (first coll))
(recur (conj res group) [] (next coll))
(recur res group (next coll))))
(if (seq curr)
(conj res curr)
res))))
答复:
user> (map (partial group-loop 2)
[[]
nil
[1 2 3 1 2 3]
[1 2 3 1 2 3 2]
[2 1 2 3 1 2 3]
[1 3 4 1 3 4]])
;;([] []
;; [[1 2] [3 1 2] [3]]
;; [[1 2] [3 1 2] [3 2]]
;; [[2] [1 2] [3 1 2] [3]]
;; [[1 3 4 1 3 4]])
虽然它看起来有点过于冗长,但它仍然有一些相当重要的优点:首先,它是一种经典(我认为它是赞成的而不是反对的),第二,它很快(根据我的基准测试,它比reduce
variant快3倍,比partition
variant快6到10倍)
此外,您还可以通过一些小的调整使其更加简洁,像clojure的序列操作函数那样返回惰性集合:
(defn group-lazy [delim coll]
(loop [curr [] coll coll]
(if (seq coll)
(let [curr (conj curr (first coll))]
(if (= delim (first coll))
(cons curr (lazy-seq (group-lazy delim (rest coll))))
(recur curr (next coll))))
(when (seq curr) [curr]))))
user> (map (partial group-lazy 2)
[[]
nil
[1 2 3 1 2 3]
[1 2 3 1 2 3 2]
[2 1 2 3 1 2 3]
[1 3 4 1 3 4]])
;;(nil nil
;; ([1 2] [3 1 2] [3])
;; ([1 2] [3 1 2] [3 2])
;; ([2] [1 2] [3 1 2] [3])
;; [[1 3 4 1 3 4]])
您需要拆分数字向量还是任意对象向量?