如何使用开始/停止谓词对列表的连续元素进行分组?

Ala*_*son 4 clojure

假设我有一个列表,如:

(def data [:a :b :c :d :e :f :g :h :b :d :x])
Run Code Online (Sandbox Code Playgroud)

和谓词如:

(defn start? [x] (= x :b))
(defn stop?  [x] (= x :d))
Run Code Online (Sandbox Code Playgroud)

标记子序列的第一个和最后一个元素.我想返回一个包含子组的列表,如下所示:

(parse data) => [:a [:b :c :d] :e :f :g :h [:b :d] :x]
Run Code Online (Sandbox Code Playgroud)

如何使用Clojure完成此任务?

exu*_*ero 5

您可以使用自定义有状态传感器:

(defn subgroups [start? stop?]
  (let [subgroup (volatile! nil)]
    (fn [rf]
      (fn
        ([] (rf))
        ([result] (rf result))
        ([result item]
         (let [sg @subgroup]
           (cond
             (and (seq sg) (stop? item))
             (do (vreset! subgroup nil)
               (rf result (conj sg item)))
             (seq sg)
             (do (vswap! subgroup conj item)
               result)
             (start? item)
             (do (vreset! subgroup [item])
               result)
             :else (rf result item))))))))

(into []
      (subgroups #{:b} #{:d})
      [:a :b :c :d :e :f :g :h :b :d :x])
; => [:a [:b :c :d] :e :f :g :h [:b :d] :x]
Run Code Online (Sandbox Code Playgroud)