递归后返回列表是多余的

时间:2012-02-18 21:46:11

标签: list recursion common-lisp

我是Lisp的新手,在将列表附加到现有列表时遇到问题。

(Funcion spec)以下函数需要2个参数;原子和列表。该列表采用二维形式,其中每个子列表看起来像(index counter)(索引和计数器都是原子)。如果target等于index es之一,counter增量。如果没有子列表包含target,请添加counter = 1的新子列表。

(defun contained (target list)
  (cond ((null list) (list target 1))
    ((= (car (car list)) target)
     (setf (cadr (car list))
           (+ (cadr (car list)) 1)))
    (t (push (contained target (cdr list)) list))))

问题是target尚不存在。如下所示,列表和括号变得多余。

> la
((1 4) (2 1))
> (contained 3 la)
(((3 1) (2 1)) (1 4) (2 1))

我想要的是:

((3 1) (1 4) (2 1))

很抱歉没有能够简化问题,但谢谢。

1 个答案:

答案 0 :(得分:2)

(defun contained (target list)
  (cond
    ((null list) (list target 1)) ; you are returning a new element of target

    ((= (car (car list)) target)
     (setf (cadr (car list))
           (+ (cadr (car list)) 1))) ; you are returning... what?

    ;; yet you are pushing on every recursive call!
    (t (push (contained target (cdr list)) list))))

冒着为你做功课的风险,这是一种方法(在Miron Brezuleanu的帮助下):

(defun contained (target list)
    (let ((elm (assoc target list)))
        (if elm 
            (progn (incf (cadr elm)) list)
            (cons (list target 1) list))))

这是一种更接近原始

的方法
(defun contained (target list)
  (cond
    ((null list) (list (list target 1)))
    ((= (car (car list)) target)
     (setf (cadr (car list))
           (+ (cadr (car list)) 1))
     list)
    (t (setf (cdr list) (contained target (cdr list)))
       list)))