如何在迭代中访问seq中的两个相邻元素

mur*_*a52 1 clojure

我有一个seq (2 3 1 4).

我想迭代它,并且当下一个元素更小时,prev元素将替换两个元素另一个seq.'( - 4 1).

所以f('(2 3 1 4))=>(2( - 3 1)4).我怎么写呢?

基本上 -

1)我想同时访问seq中的两个相邻元素.2)编辑并返回该点的新seq.3)继续处理新返回的seq.

一般来说,实现上述3的机制是什么.(map,reduce都让我一次只能访问一个elem.)

Fra*_*ila 5

这实际上不是成对消费的问题,因为您对序列进行分区的方式取决于您对当前对的处理方式.请注意,有时您会从sequence()中使用一个项目2 3,但有时您会使用两个项目(3 1).

正因为如此,你不能使用任何的创造Clojure中的滑动窗口(通常的方法(partition 2 1 coll),(map fn coll (rest coll))等等).您需要使用明确递归的内容.

你的算法应该是这样的:

  1. 如果空seq发出nil
  2. 如果只有一个项目发出项目
  3. 如果有两个项目,请测试尺寸:
    1. 如果第一个>第二个,则替换为(- first second); 递归剩余物品
    2. 否则,先排出; 递归第二个和剩余的项目.

这是该算法的惰性实现.你也可以使用recur和累加器这样做- 它不会是懒惰但它仍然可以工作.

(defn combine-if-gt-next
  [[f s & r]]
  (cond
   (nil? f) nil
   (nil? s) (cons f nil)
   (> f s)  (cons (list '- f s) (lazy-seq (combine-if-gt-next r)))
   true (cons f (lazy-seq (combine-if-gt-next (cons s r))))))
Run Code Online (Sandbox Code Playgroud)

例子:

(combine-if-gt-next '(2 3 1 4)) ; your example
;; (2 (- 3 1) 4)
(combine-if-gt-next [])
;; nil
(combine-if-gt-next [1 2 3])
;; (1 2 3)
(combine-if-gt-next [2 3 4 1])
;; (2 3 (- 4 1))
(combine-if-gt-next [2 3 4 1 4])
;; (2 3 (- 4 1) 4)
(combine-if-gt-next [2 1 4 1 4 5 1])
;; ((- 2 1) (- 4 1) 4 (- 5 1))
(combine-if-gt-next [5 4 3 2 1])
;; ((- 5 4) (- 3 2) 1)
Run Code Online (Sandbox Code Playgroud)