Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 元素每次出现后分割向量_Clojure - Fatal编程技术网

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]])

您需要拆分数字向量还是任意对象向量?