我有一个函数,它获取 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)),但是我在编辑的时候忘记去掉‘#’了。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top