题
我有一个函数,它获取 x(一个值)和 xs(一个列表)并从列表中删除所有大于 x 的值。嗯,它不起作用,你能告诉我为什么吗?
(defun biggerElems(x xs)
(let ((xst))
(dolist (elem xs)
(if (> x elem)
(setf xst (remove elem xs))))
xst))
解决方案
我认为这一行是不正确的:
(setf xst (remove elem xs))))
第一个参数 setf
是地点,其次是值。看起来你把它弄反了(并且 xst
或者是 nil
或未初始化)。
您可能会发现这样做更容易:
(defun biggerElems (x xs)
(remove-if (lambda (item) (> item x)) xs))
其他提示
最简洁的据我所知:
(defun bigger-elements (x xs) (remove x xs :test #'<))
返回一个新列表,它从 xs 中删除所有元素 y
(< y x)
或者使用著名的循环:
(defun bigger-elements-2 (x xs)
(loop for e in xs
unless (< e x)
collect e))
它是这样工作的:
(defun filterBig (x xs)
(remove-if (lambda (item) (> item x)) xs))
'#' 是做什么用的?它没有与它一起编译。
如果您想以 Lisp 方式执行此操作,可以使用递归来返回新列表:
(defun biggerElems (x xs)
(cond ((null xs) NIL)
((< x (car xs))
(biggerElems x (cdr xs)))
(t
(cons (car xs) (biggerElems x (cdr xs))))))
@路易斯奥利维拉
该解决方案与问题中发布的解决方案形成对比。如果我们需要做一些稍微复杂的事情,那么基于递归方法来操作列表就很重要。
@本:这并不是 setf 调用是错误的——问题是他没有更新 xs。
IE:xst 被设置为 xs 并删除了元素,但 xs 没有被更新。如果要删除第二个元素,xst 会将第一个元素放回其中。
您需要将 xst 绑定到 xs,并将删除调用中的 xs 替换为 xst。这将删除所有大于 x 的元素。IE:
(defun biggerElems(x xs)
(let ((xst xs))
(dolist (elem xs)
(when (> x elem)
(setf xst (remove elem xst))))
xst))
将 xst 设置为 (copy-list xs) 然后使用删除而不是删除可能会稍快一些(删除具有破坏性......根据您的实现,它可能比删除更快。由于您多次调用此函数,因此复制列表一次并从中进行破坏性删除可能会获得更好的性能)。
或者:
(defun bigger-elems (x xs) ; I prefer hyphen separated to camelCase... to each his own
(loop for elem in xs when (<= x elem) collect elem))
回顾一下你原来的帖子,有点混乱......您说您删除了所有大于 x 的元素,但您的代码看起来像是试图删除所有大于 x 的元素。我编写的解决方案返回所有大于 x 的元素(即:删除所有 x 大于的元素)。
'#' 是做什么用的?它没有编译。
错字。通常你用以下方式引用函数 #'
(喜欢 (remove-if #'oddp list)
),但是我在编辑的时候忘记去掉‘#’了。