4

我有一个函数可以获取 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))
4

6 回答 6

5

我认为这是不对的这条线:

(setf xst (remove elem xs))))

to的第一个参数setf是位置,然后是值。看起来你有它倒退(或者xstnil或者未初始化)。

您可能会发现这样做更容易:

(defun biggerElems (x xs)
  (remove-if (lambda (item) (> item x)) xs))
于 2008-09-05T18:06:23.810 回答
4

最简洁的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))
于 2008-09-16T14:28:35.957 回答
1

它是这样工作的:

(defun filterBig (x xs)
  (remove-if (lambda (item) (> item x)) xs))

'#' 是干什么用的?它没有用它编译。

于 2008-09-05T18:26:04.167 回答
1

如果您想以 Lisp 方式执行此操作,可以使用递归返回新列表:

(defun biggerElems (x xs)
  (cond ((null xs) NIL)
        ((< x (car xs))
         (biggerElems x (cdr xs)))
       (t
        (cons (car xs) (biggerElems x (cdr xs))))))

@路易斯奥利维拉

此解决方案与问题中发布的解决方案形成对比。如果我们需要做一些稍微复杂的事情,重要的是要以递归方法来操作列表。

于 2008-09-05T18:33:24.057 回答
1

@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 大于的元素)。

于 2008-09-22T22:38:47.557 回答
0

'#' 是干什么用的?它没有用它编译。

错字。#'通常你用(like )来引用函数(remove-if #'oddp list),但是当我在编辑时,我忘了删除'#'。

于 2008-09-05T18:32:20.907 回答