代码之家  ›  专栏  ›  技术社区  ›  Jacky

编辑列表中的每个偶数索引元素

  •  1
  • Jacky  · 技术社区  · 8 年前

    我对lisp还很陌生,我想让每个索引元素都替换为包含此元素的新元素列表。例如

    (1 2 3 4 5)->(1(2)3(4)5),(1 2 3 4 5 6)->(1(2)3(4)5(6))

    现在我想出了一个解决方案,每个元素都放在自己的列表中,但我无法确切地知道如何选择每个索引元素:

    (DEFUN ON3 (lst)
     ((ATOM (CDR lst)) (CONS (CONS (CAR lst) NIL) NIL))
     (CONS (CONS (CAR lst) NIL) (ON3 (CDR lst)))) 
    
    2 回复  |  直到 8 年前
        1
  •  2
  •   Sylwester    8 年前

    你的代码不起作用。您需要使用 if 或 cond 使代码遵循其中的一条路径。现在,您在调用一个名为 (atom (cdr lst)) 。如果它曾经运行过,那么它将是死代码,因为下一行始终是运行的。它是无限递归。

    那么如何计数呢。您可以将每个步骤视为一次处理两个元素的句柄。您需要注意以下事项:

    (enc-odds '())         ; ==> ()
    (enc-odds '(1))        ; ==> (1)
    (enc-odds '(1 2 3 ...) ; ==> (1 (2) (enc-odds (3 ...))
    

    另一种方法是使用额外的参数创建助手:

    (defun index-elements (lst)
      (labels ((helper (lst n)
                 (if (null lst)
                     lst
                     (cons (list (car lst) n)
                           (helper (cdr lst) (1+ n))))))
        (helper lst 0)))
    (index-elements '(a b c d))
    ; ==> ((a 0) (b 1) (c 2) (d 3))
    
        2
  •  2
  •   ptb    8 年前

    对于非递归解决方案,循环允许构造同时迭代器:

    (defun every-second (list)
      (loop
          for a in list
          for i upfrom 1
          if (evenp i) collect (list a)
          else collect a))
    
    (every-second '(a b c d e))
    ; ==> (A (B) C (D) E) 
    

    看见 http://www.gigamonkeys.com/book/loop-for-black-belts.html 为了更好地解释循环