我有一个函数可以获取 x(a value) 和 xs(a list) 并从列表中删除所有大于 x 的值。那么它不起作用,你能告诉我为什么吗?
(defun biggerElems(x xs)
(let ((xst))
(dolist (elem xs)
(if (> x elem)
(setf xst (remove elem xs))))
xst))
我认为这是不对的这条线:
(setf xst (remove elem xs))))
to的第一个参数setf
是位置,然后是值。看起来你有它倒退(或者xst
是nil
或者未初始化)。
您可能会发现这样做更容易:
(defun biggerElems (x xs)
(remove-if (lambda (item) (> item x)) xs))
最简洁的AFAIK:
(defun bigger-elements (x xs) (remove x xs :test #'<))
返回一个新列表,它从 xs 中删除所有元素 y
(< y x)
或使用著名的 LOOP:
(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))))))
@路易斯奥利维拉
此解决方案与问题中发布的解决方案形成对比。如果我们需要做一些稍微复杂的事情,重要的是要以递归方法来操作列表。
@Ben:不是 setf 调用是错误的——问题是他没有更新 xs。
即: xst 被设置为 xs 并删除了元素,但 xs 没有被更新。如果要删除第二个元素,xst 将在其中包含第一个元素。
您需要将 xst 绑定到 xs,并将 remove 调用中的 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) 然后使用 delete 而不是 remove (delete 是破坏性的......取决于您的实现,它可能比 remove 更快。由于您多次调用它,您一次复制列表并从列表中破坏性删除可能会获得更好的性能)。
或者:
(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 大于的元素)。
'#' 是干什么用的?它没有用它编译。
错字。#'
通常你用(like )来引用函数(remove-if #'oddp list)
,但是当我在编辑时,我忘了删除'#'。