如何在分隔符上拆分矢量

时间:2014-05-08 19:32:13

标签: clojure

我有一个包含数字的向量。 矢量的结构如下:

  1. 任意长度的项目
  2. 项目之间的分隔符[0 0 0 0 0](0重复5次)
  3. 我想写一个函数split来检索项目列表(没有分隔符):它类似于string/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万。

    感谢您的帮助。

3 个答案:

答案 0 :(得分:4)

下面:

(defn the-split [coll] 
  (let [part   (partition-by identity coll)
        ppart  (partition-by #(= [0 0 0 0 0] %) part)
        almost (map #(apply concat %) ppart)]
    (filter (partial not= [0 0 0 0 0]) almost)))


(the-split [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))

答案 1 :(得分:2)

这是一种方法 - 将[0 0 0 0 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])

如果您希望输出为向量而不是seq的向量,请将vec换行。

另一种方法 - 这次热切地使用loop / recur消费输入:

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

答案 2 :(得分:1)

懒惰的解决方案:

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