Clojure 如何在分隔符上拆分向量
我有一个包含数字的向量。 向量的结构如下所示:Clojure 如何在分隔符上拆分向量,clojure,Clojure,我有一个包含数字的向量。 向量的结构如下所示: 任意长度的项目 项目之间的分隔符[0 0](0重复5次) 我想编写一个函数split,用于检索项目列表(不带分隔符):它类似于 例如: (split [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 199]) ; => [[123 0 1] [1 1] [1 0 1] [0 0 1 199]] 备注:该代码必须有效,因为向量的长度约为100万。 感谢您的帮助。这里有一种方法--使
split
,用于检索项目列表(不带分隔符):它类似于
例如:
(split [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 199])
; => [[123 0 1] [1 1] [1 0 1] [0 0 1 199]]
备注:该代码必须有效,因为向量的长度约为100万。
感谢您的帮助。这里有一种方法--使用硬连线的[0]
分隔符,但很容易概括:
(defn split5z [xs]
(let [delim [0 0 0 0 0]
step (fn step [xs seg]
(lazy-seq
(if-let [xs (seq xs)]
(let [window (take 5 xs)]
(if (= window delim)
(cons seg (step (drop 5 xs) []))
(step (rest xs) (conj seg (first xs)))))
(list seg))))]
(step xs [])))
将其应用于示例输入:
(split5z [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 199])
;= ([123 0 1] [1 1] [1 0 1] [1 199])
如果希望输出为向量而不是一系列向量,请使用vec
另一种方法——这段时间急切地使用循环
/重复
:
(defn split5z [sep xs]
(let [scnt (count sep)]
(loop [xs (seq xs)
out []
seg []]
(if xs
(if (= (take scnt xs) sep)
(recur (nthnext xs scnt)
(conj out seg)
[])
(recur (next xs)
out
(conj seg (first xs))))
(if (seq seg)
(conj out seg)
seg)))))
在REPL上:
(split5z [0 0 0 0 0]
[123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 199])
;= [[123 0 1] [1 1] [1 0 1] [1 199]]
在这里:
懒惰的解决方案:
(defn split [v]
(let [delim (repeat 5 0)
i (->> v (partition 5 1) (take-while #(not= delim %)) count)]
(if (zero? i) [v] (lazy-seq (cons (subvec v 0 i)
(split (subvec v (+ i 5))))))))
比如说
(split [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 199])
; ([123 0 1] [1 1] [1 0 1] [0 0 1 199])
很好,但是如果
0
启动或结束有效的数据块:(拆分[01 0 0 0 0 2]);=>((01 0 0 0 2))
。然而,语法对于((01)(02))
或((0110)(2))
是否正确是不明确的。@A.韦伯完全正确。如果有6个或更多的零对齐,分隔符应该是前5个零还是最后5个零?也许问题的作者有一个线索。…。@a.Webb不仅语法模棱两可,而且据我所知,它并没有对所有可能的项目列表进行编码:例如,我无法设计出解码为[[1 0][0 1]]
的向量。我已经向OP询问了这个问题。@A.Webb我需要与相同的行为。项目列表:[[1 0][0 1]]
可行吗?分裂成它的向量是什么?@Thumbnail我需要与相同的行为。
(split [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 199])
; ([123 0 1] [1 1] [1 0 1] [0 0 1 199])