在Clojure中,我可以通过将step
参数调整为partition
来获得集合的重叠分区:
(partition 3 1 (range 20))
;; ((0 1 2) (1 2 3) (2 3 4) (3 4 5) ...)
core.async确实具有分区功能,但是由于它不接受step参数,因此无法获得重叠的分区:
(let [c (chan)]
(go (doseq [n (range 20)]
(>! c n)))
(go-loop [p (async/partition 3 c)]
(when-let [v (<! p)]
(prn v)
(recur p))))
;;[0 1 2]
;;[3 4 5]
;;[6 7 8]
我意识到拥有这可能意味着能够多次从一个通道读取相同的值。我也知道我可以创建自己的函数,该函数可以根据需要从通道读取尽可能多的值,并构建自己的分区。
但是我想知道是否有任何办法可以使用core.async提供的核心API来实现这一目标。
PS。
sliding-buffer
不能解决问题,因为我无法一次浏览整个缓冲区。 最佳答案
一种方法是创建一个从通道读取,缓冲值并放入新通道的函数。我不确定这是多么惯用。
例如,每当从输入通道中读取所需的put!
项目时,下面的函数就会将矢量n
进入输出通道,并在每次输出后跳过step
项目。
(defn stepped-partition [in n step]
(let [out (chan)]
(go-loop [buffer []]
(when-let [v (<! in)]
(let [new-buffer (conj buffer v)]
(if (= (count new-buffer) n)
(do
(put! out new-buffer)
(recur (subvec new-buffer step)))
(recur new-buffer)))))
out))
(def original (chan))
(def partitioned (stepped-partition a 3 2))
(go-loop []
(when-let [v (<! partitioned)]
(println v)
(recur)))
(async/onto-chan original [1 2 3 4 5 6 7 8 9])
;=> [1 2 3]
;=> [3 4 5]
;=> [5 6 7]
;=> [7 8 9]