Common lisp:遍历成对的列表
Common lisp: loop through pairs of a list
我有一个长度可以被 2 整除的列表,我正在寻找与 this 问题的答案类似的内容:
(loop for (a b) on lst while b
collect (+ a b))
但是元素之间有重叠:
(1 2 3 4 5) -> (3 5 7 9)
相加 1 和 2,然后相加 2 和 3 等等
因为我有一个像 (1 2 3 4)
这样的列表并且正在寻找像
这样的东西
((1 2) (3 4))
作为输出。有没有办法让循环在列表中正确执行?
另一个解决方案。
像这样的东西应该可以工作:
(let ((list '(1 2 3 4)))
(loop :for (a b) :on list :by #'cddr :while b
:collect (cons a b)))
还有一个更详细的变体:
(let ((list '(1 2 3 4)))
(loop :for a :in list :by #'cddr
:for b :in (cdr list) :by #'cddr
:collect (cons a b)))
另一种使用 SERIES 包的方法。
另见 Richard C. Waters 的 user manual。
设置
(ql:quickload :series)
(defpackage :Whosebug (:use :series :cl))
(in-package :Whosebug)
代码
(defun pairs (list)
(collect 'list
(mapping (((odd even) (chunk 2 2 (scan 'list list))))
(list odd even))))
scan
list
的内容作为 "serie"
chunk
M=2 和 N=2:
This function has the effect of breaking up the input series items
into (possibly overlapping) chunks of length m. The starting positions
of successive chunks differ by n. The inputs m and n must both be
positive integers.
更准确地说,(chunk 2 2 (scan '(1 2 3 4)))
产生 #Z(1 3)
和 #Z(2 4)
mapping
并行处理这些系列的每个 odd
和 even
元素,产生一系列对,如 (list odd even)
所做的那样。
最后,collect
结果,作为列表。
编译
由于流融合机制,所有中间 "series" 都被编译掉了。这是指向 collect
:
时的宏扩展
(LET* ((#:OUT-1120 LIST))
(LET (#:ELEMENTS-1117
(#:LISTPTR-1118 #:OUT-1120)
(#:COUNT-1113 0)
#:CHUNK-1114
#:CHUNK-1115
#:ITEMS-1123
(#:LASTCONS-1106 (LIST NIL))
#:LST-1107)
(DECLARE (TYPE LIST #:LISTPTR-1118)
(TYPE FIXNUM #:COUNT-1113)
(TYPE CONS #:LASTCONS-1106)
(TYPE LIST #:LST-1107))
(SETQ #:COUNT-1113 1)
(SETQ #:LST-1107 #:LASTCONS-1106)
(TAGBODY
#:LL-1124
(IF (ENDP #:LISTPTR-1118)
(GO SERIES::END))
(SETQ #:ELEMENTS-1117 (CAR #:LISTPTR-1118))
(SETQ #:LISTPTR-1118 (CDR #:LISTPTR-1118))
(SETQ #:CHUNK-1114 #:CHUNK-1115)
(SETQ #:CHUNK-1115 #:ELEMENTS-1117)
(COND ((PLUSP #:COUNT-1113) (DECF #:COUNT-1113) (GO #:LL-1124))
(T (SETQ #:COUNT-1113 1)))
(SETQ #:ITEMS-1123
((LAMBDA (ODD EVEN) (LIST ODD EVEN)) #:CHUNK-1114 #:CHUNK-1115))
(SETQ #:LASTCONS-1106
(SETF (CDR #:LASTCONS-1106) (CONS #:ITEMS-1123 NIL)))
(GO #:LL-1124)
SERIES::END)
(CDR #:LST-1107)))
CL-USER 156 > (loop with list = '(1 2 3 4)
while list
collect (loop repeat 2
while list
collect (pop list)))
((1 2) (3 4))
或
CL-USER 166 > (loop with list = '(1 2 3 4 5 6)
while (and list (cdr list))
collect (loop repeat 2 collect (pop list)))
((1 2) (3 4) (5 6))
CL-USER 167 > (loop with list = '(1 2 3 4 5 6 7)
while (and list (cdr list))
collect (loop repeat 2 collect (pop list)))
((1 2) (3 4) (5 6))
我有一个长度可以被 2 整除的列表,我正在寻找与 this 问题的答案类似的内容:
(loop for (a b) on lst while b
collect (+ a b))
但是元素之间有重叠:
(1 2 3 4 5) -> (3 5 7 9)
相加 1 和 2,然后相加 2 和 3 等等
因为我有一个像 (1 2 3 4)
这样的列表并且正在寻找像
((1 2) (3 4))
作为输出。有没有办法让循环在列表中正确执行? 另一个解决方案。
像这样的东西应该可以工作:
(let ((list '(1 2 3 4)))
(loop :for (a b) :on list :by #'cddr :while b
:collect (cons a b)))
还有一个更详细的变体:
(let ((list '(1 2 3 4)))
(loop :for a :in list :by #'cddr
:for b :in (cdr list) :by #'cddr
:collect (cons a b)))
另一种使用 SERIES 包的方法。 另见 Richard C. Waters 的 user manual。
设置
(ql:quickload :series)
(defpackage :Whosebug (:use :series :cl))
(in-package :Whosebug)
代码
(defun pairs (list)
(collect 'list
(mapping (((odd even) (chunk 2 2 (scan 'list list))))
(list odd even))))
scan
list
的内容作为 "serie"chunk
M=2 和 N=2:This function has the effect of breaking up the input series items into (possibly overlapping) chunks of length m. The starting positions of successive chunks differ by n. The inputs m and n must both be positive integers.
更准确地说,
(chunk 2 2 (scan '(1 2 3 4)))
产生#Z(1 3)
和#Z(2 4)
mapping
并行处理这些系列的每个odd
和even
元素,产生一系列对,如(list odd even)
所做的那样。最后,
collect
结果,作为列表。
编译
由于流融合机制,所有中间 "series" 都被编译掉了。这是指向 collect
:
(LET* ((#:OUT-1120 LIST))
(LET (#:ELEMENTS-1117
(#:LISTPTR-1118 #:OUT-1120)
(#:COUNT-1113 0)
#:CHUNK-1114
#:CHUNK-1115
#:ITEMS-1123
(#:LASTCONS-1106 (LIST NIL))
#:LST-1107)
(DECLARE (TYPE LIST #:LISTPTR-1118)
(TYPE FIXNUM #:COUNT-1113)
(TYPE CONS #:LASTCONS-1106)
(TYPE LIST #:LST-1107))
(SETQ #:COUNT-1113 1)
(SETQ #:LST-1107 #:LASTCONS-1106)
(TAGBODY
#:LL-1124
(IF (ENDP #:LISTPTR-1118)
(GO SERIES::END))
(SETQ #:ELEMENTS-1117 (CAR #:LISTPTR-1118))
(SETQ #:LISTPTR-1118 (CDR #:LISTPTR-1118))
(SETQ #:CHUNK-1114 #:CHUNK-1115)
(SETQ #:CHUNK-1115 #:ELEMENTS-1117)
(COND ((PLUSP #:COUNT-1113) (DECF #:COUNT-1113) (GO #:LL-1124))
(T (SETQ #:COUNT-1113 1)))
(SETQ #:ITEMS-1123
((LAMBDA (ODD EVEN) (LIST ODD EVEN)) #:CHUNK-1114 #:CHUNK-1115))
(SETQ #:LASTCONS-1106
(SETF (CDR #:LASTCONS-1106) (CONS #:ITEMS-1123 NIL)))
(GO #:LL-1124)
SERIES::END)
(CDR #:LST-1107)))
CL-USER 156 > (loop with list = '(1 2 3 4)
while list
collect (loop repeat 2
while list
collect (pop list)))
((1 2) (3 4))
或
CL-USER 166 > (loop with list = '(1 2 3 4 5 6)
while (and list (cdr list))
collect (loop repeat 2 collect (pop list)))
((1 2) (3 4) (5 6))
CL-USER 167 > (loop with list = '(1 2 3 4 5 6 7)
while (and list (cdr list))
collect (loop repeat 2 collect (pop list)))
((1 2) (3 4) (5 6))