我目前正在尝试创建一个向列表中间的值加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。感谢
答案 0 :(得分:1)
你走了:
(defun add-1 (list)
(let ((len (length list)))
(assert (oddp len) (list))
(incf (nth (/ (1- len) 2) list))))
答案 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))
用法:
(middle '((1 4 6 7 8) (3 4 2)))
=> ((1 4 7 7 8) (3 5 2))
(middle '((1 4 6 7) (3 4 2)))
=> ((1 4 6 7) (3 5 2))
(middle '(2 3 4))
=> (2 4 4)
(middle '(2 3 4 5)
=> (2 3 4 5)