LISP(在列表中间加一个值)

时间:2015-02-25 22:01:37

标签: lisp common-lisp

我目前正在尝试创建一个向列表中间的值加1的函数。

Example: (add1 '(2 4 6 5 9)) -> (2 4 7 5 9)

此外,如果列表是偶数,则不返回任何内容。到目前为止,我有一个函数返回列表中间的位置。

(defun add1(aList)
               (if (oddp (length aList)) (- (/ (length aList) 2) .5) 'EvenNumber))

示例:(add1'(2 4 6 5 9)) - > 2.0

有没有办法使用这些信息来获取中间的值然后加1。感谢

4 个答案:

答案 0 :(得分:1)

你走了:

(defun add-1 (list)
  (let ((len (length list)))
    (assert (oddp len) (list))
    (incf (nth (/ (1- len) 2) list))))

如果您不希望偶数长度列表出错,请将assert替换为when

答案 1 :(得分:1)

这是一个函数,它只通过列表两次而不是修改原始函数,并且不对整数执行任何算术:

(defun inc-middle-elt (list)
  (loop for elem in list
        for pair = list then (cddr pair)
        with flag = t
        when (and flag (null (cddr pair))) do
          (if (null (cdr pair))
            (incf elem))
          (setf flag nil)
        collect elem))

为了找到中间部分,这使用了与链接列表的二进制合并排序的实现中使用的类似技巧:辅助指针pair以双步跨越列表,跨越对。

(cddr pair)nil时,我们处于最后一对。此时,必须做出决定:列表是否包含奇数项目?如果列表中的项目数为奇数,那么在(cddr pair)nil的最后一对位置,只剩下一个元素:(cdr pair)也为零。

练习:利用列表中间后面的元素不需要复制的事实来优化这个功能;输出列表可以共享输入列表的尾部。此外,更改函数,以便在清除时没有中间元素时,它将返回原始列表。

答案 2 :(得分:0)

尝试这样的事情。

(defun add1 (lst)
  (when (oddp (length lst))
    (incf (nth (floor (/ (length lst) 2)) lst)))
  lst)

我认为您需要的缺失部分是setf(您可能已经使用过它,但也许您并不知道可以使用表单第一个参数)或在这种情况下incf(增加一个或可选的指定增量)。它们允许您使用表达式来获取需要设置的值。

要考虑的一些事情(如书面所述):

  • 这是一次破坏性更新
  • 在同一个列表中多次调用length。这可能很昂贵。
  • 正如我所写,偶数长度列表只是不改变列表。这不是你要求的,但也许你想要的。
  • 我使用了floor而不是在减去.5,这需要一些额外的投射。

答案 3 :(得分:0)

我希望您正在寻找递归版

(defun middle (lis)
 (let ((lis (c-in-place lis)))
  (cond ((null lis) nil) ((atom lis) lis)
   (t
    (mapcar
     #'(lambda (x)
        (cond ((atom x) x) (t (mapcar #'c-in-place (c-in-place x)))))
     lis)))))


(defun c-in-place (lis)
 (cond
  ((and (listp lis) (oddp (length lis)) (> (length lis) 2))
   (let ((pos (1+ (floor (/ (length lis) 2)))))
    (in-place (1+ (nth (floor (/ (length lis) 2)) lis)) pos lis)))
  (t lis)))

(defun in-place (nxt n lis)
 (let (temp temp1) (setf temp (subseq lis 0 (- n 1)))
  (setf temp1 (subseq lis n)) (setf temp (append temp (append `(,nxt) temp1)))
  temp))     

用法:

  1. (middle '((1 4 6 7 8) (3 4 2))) => ((1 4 7 7 8) (3 5 2))
  2. (middle '((1 4 6 7) (3 4 2))) => ((1 4 6 7) (3 5 2))
  3. (middle '(2 3 4)) => (2 4 4)
  4. (middle '(2 3 4 5) => (2 3 4 5)