常见的lisp:遍历列表对

che*_*yst 4 lisp sbcl common-lisp

我有一个列表,其长度可以被2整除,我正在寻找类似于这个问题的答案:

(loop for (a b) on lst while b
      collect (+ a b))
Run Code Online (Sandbox Code Playgroud)

但是元素之间存在重叠:

(1 2 3 4 5) -> (3 5 7 9)
Run Code Online (Sandbox Code Playgroud)

添加1和2,然后添加2和3等.

我在哪里有一个列表(1 2 3 4),我正在寻找类似的东西

((1 2) (3 4))
Run Code Online (Sandbox Code Playgroud)

作为输出.有没有办法在列表上正确地循环步骤?另一种方法.

cyb*_*vnm 6

这样的事情应该有效:

(let ((list '(1 2 3 4)))
  (loop :for (a b) :on list :by #'cddr :while b 
        :collect (cons a b)))
Run Code Online (Sandbox Code Playgroud)

也是一个更冗长的变体:

(let ((list '(1 2 3 4)))
  (loop :for a :in list :by #'cddr
        :for b :in (cdr list) :by #'cddr
        :collect (cons a b)))
Run Code Online (Sandbox Code Playgroud)

  • @cheshirecatalyst抱歉,不确定你是什么意思.它应该与其他循环选项(dolist,mapcar等)一样快,使用":by"关键字的事实不应该使循环更慢,实际上它将减少两次步骤. (2认同)

cor*_*ump 5

使用SERIES包的另一种方法 。另请参阅Richard C. Waters 的用户手册

设定

(ql:quickload :series)
(defpackage :stackoverflow (:use :series :cl))
(in-package :stackoverflow)
Run Code Online (Sandbox Code Playgroud)

(defun pairs (list)
  (collect 'list
    (mapping (((odd even) (chunk 2 2 (scan 'list list))))
      (list odd even))))
Run Code Online (Sandbox Code Playgroud)
  • scan内容list为“意甲”
  • chunk 它的M = 2和N = 2:

    该功能具有将输入系列项分解为(可能重叠)长度为m的块的效果。连续块的起始位置相差n。输入m和n必须都为正整数。

    更确切地说,(chunk 2 2 (scan '(1 2 3 4)))生产#Z(1 3)#Z(2 4)

  • mapping在这些系列的每个oddeven元素上并行生成一对夫妇,如(list odd even)

  • 最后,collect将结果作为列表。

汇编

借助流融合机制,所有中间“系列”都被编译掉了。这是指向时的宏扩展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)))
Run Code Online (Sandbox Code Playgroud)