Common Lisp:检查元素是否为列表成员的函数

时间:2013-12-11 21:33:05

标签: common-lisp

我想创建一个函数来检查元素是否是列表的成员。该列表可以包含其他列表。 这是我到目前为止所得到的:

(defun subl(l)
  (if (numberp l)
      (if (= l 10)
          (princ "Found"))
      (mapcar 'subl l)))

现在我搜索的号码是硬编码的,是10。我想以某种方式编写它,所以函数接受另一个参数(我正在搜索的数字)并在找到它时返回true1。主要问题是我看不到控制mapcar的方法。如果mapcar列表,则subl会在l的每个元素上执行l。但是,如何控制每次调用的返回值?

我想检查每个subl来电的返回值,如果其中一个是true1,则返回true1直到最后一次递归调用。因此,如果元素包含在列表中,subl会返回trueone,否则会返回nil

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

mapcar是一个非常通用的原语,用于在列表上映射函数。您可以使用其中一个内置组合器,它更适合您要做的事情。查看member函数。

答案 1 :(得分:2)

你的功能似乎同时扮演主要功能和助手的角色。这使得你的代码比它必须更难理解..

所以想象你把这两个分开了:

;; a predicate to check if an element is 10
(defun number10p (l)
    (and (numberp l)
         (= l 10)))

;; the utility function to search for 10 amongst elements
(defun sublistp (haystack)
    (mapcar #'number10p haystack)))

但是当你执行(sublistp '(5 10 15 20))时,你会得到(nil t nil nil)。那是因为mapcar列出了每个结果。对我而言,似乎你正在描述some因为它停在第一个真值。

(defun sublistp (haystack)
    (some #'number10p haystack)))

(sublistp '(5 10 15 20)) ; ==> t

现在为了使它适用于任何数据类型,我们更改谓词并将其作为本地函数,我们有我们正在搜索的参数:

(defun sublistp (needle haystack)
  (flet ((needlep (x)
            (equal x needle)))
    (some #'needlep haystack)))

(sublistp '(a b) '(a b c (a b) d e f)) ; ==> t

你也可以使用这样的匿名谓词:

(defun sublistp (needle haystack)
  (some #'(lambda (x)
            (equal x needle))
        haystack))

这是member函数的实现,除了它将匹配作为真值返回。这没关系,因为nil中只有CL之内的任何内容都是正确的:

(member 10 '(5 10 15 20)) ; ==> (10 15 20) 

修改 您评论了一个不同的答案,您需要使用mapcar,在这种情况下将其与append一起使用以获取所有匹配项的列表并检查列表是否包含大于0的元素:

(defun sublistp (needle haystack)
  (flet ((needle-check (x)
            (if (equal x needle) '(t) nil)))
    (< 0 (length 
          (apply #'append 
                 (mapcar #'needle-check haystack))))))

它的工作原理是,对于每个匹配,您将获得一个元素的列表,并且对于每个非匹配,您将获得一个空列表。附加列表时,如果不匹配,您将获得空列表。对于所有其他结果,您有匹配。这不是一个非常有效的实现。

答案 2 :(得分:2)

以下程序应如您所述处理;

    (defun member-nested (el l)"whether el is a member of l, el can be atom or cons,
l can be list of atoms or not"
      (cond
       ((null l) nil)
       ((equal el (car l)) t)
       ((consp (car l)) (or (member-nested el (car l))
                            (member-nested el (cdr l))))
       (t (member-nested el (cdr l)))))