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

Common lisp Common Lisp:检查元素是否为列表成员的函数,common-lisp,Common Lisp,我想做一个函数,检查元素是否是列表的成员。该列表可以包含其他列表。 这就是我到目前为止的收获: (defun subl(l) (if (numberp l) (if (= l 10) (princ "Found")) (mapcar 'subl l))) 现在我搜索的号码是硬编码的,它是10。我希望以某种方式编写它,以便函数接受另一个参数(我正在搜索的数字),并在找到它时返回true或1。主要问题是我看不到控制mapcar的方法mapcar在l的

我想做一个函数,检查元素是否是列表的成员。该列表可以包含其他列表。 这就是我到目前为止的收获:

(defun subl(l)
  (if (numberp l)
      (if (= l 10)
          (princ "Found"))
      (mapcar 'subl l)))
现在我搜索的号码是硬编码的,它是
10
。我希望以某种方式编写它,以便函数接受另一个参数(我正在搜索的数字),并在找到它时返回
true
1
。主要问题是我看不到控制
mapcar
的方法<如果
l
是一个列表,则code>mapcar在
l
的每个元素上执行
subl
。但是如何控制每个调用的返回值呢

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


有什么想法吗?

mapcar
是一种非常通用的原语,用于将函数映射到列表上。您可以使用其中一个内置的组合器,它更适合您正在尝试的操作。查看函数。

mapcar
是一个非常通用的原语,用于在列表上映射函数。您可以使用其中一个内置的组合器,它更适合您正在尝试的操作。查看函数。

您的函数似乎同时扮演主函数和助手的角色。这使得您的代码比必须的更难理解

想象一下你把这两者分开:

;; 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'(510520))
时,您将返回
(nil t nil)
。这是因为
mapcar
会列出每个结果。对我来说,你似乎在描述,因为它在第一个真值处停止

(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))
该函数的一个实现是,除了它将匹配作为真值返回外。这没关系,因为在
CL
中除了
nil
以外的任何内容都是正确的:

(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))))))
(defun子列表(针式草垛)
(针检查(x)
(如果(等于x针)’(t)无)
(<0(长度
(应用#'附加)
(mapcar#“针检干草堆(#)()(#))))

它的工作原理是,对于每个匹配项,您将得到一个包含一个元素的列表,对于每个不匹配项,您将得到一个空列表。添加列表时,如果没有匹配项,则会得到空列表。对于所有其他结果,您有一个匹配项。这不是一个非常有效的实现。

您的函数似乎同时扮演主函数和助手的角色。这使得您的代码比必须的更难理解

想象一下你把这两者分开:

;; 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'(510520))
时,您将返回
(nil t nil)
。这是因为
mapcar
会列出每个结果。对我来说,你似乎在描述,因为它在第一个真值处停止

(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))
该函数的一个实现是,除了它将匹配作为真值返回外。这没关系,因为在
CL
中除了
nil
以外的任何内容都是正确的:

(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))))))
(defun子列表(针式草垛)
(针检查(x)
(如果(等于x针)’(t)无)
(<0(长度
(应用#'附加)
(mapcar#“针检干草堆(#)()(#))))

它的工作原理是,对于每个匹配项,您将得到一个包含一个元素的列表,对于每个不匹配项,您将得到一个空列表。添加列表时,如果没有匹配项,则会得到空列表。对于所有其他结果,您有一个匹配项。这不是一个非常有效的实现。

下面的过程应该按照您所描述的那样处理

    (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)))))

以下程序应按照您所述进行处理

    (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)))))

谢谢你的回答+1我真的在找类似的东西,但找不到。这是一个非常有用的函数,但不幸的是,我出于指令的原因被迫使用<代码> map < /C>:(如果你必须使用<代码> MaPCAR<代码>,请考虑将谓词映射到谓词的另一个列表中,谓词的结果应该是微不足道的,以创建自己的版本<代码> Reals。(如果无法使用内置版本)为了测试是否有任何谓词返回true。好的观点,我将尝试一下。考虑到需要传递到
mapcar
的函数只能有一个参数,有什么办法可以摆脱硬编码的
10
吗?你们有没有介绍过
lambdas
?如果你们可以使用一个,这将使练习变成trIOVAL。(只是把它传递给外部函数并在lambda中使用它)谢谢你的答案!+ 1我真的在寻找这样的东西,但是找不到。这是一个非常有用的函数,但不幸的是我不得不用<代码> map < /Cord>作为说教的理由:(如果你必须使用<代码> MMACAR< /CODE >,请考虑映射谓词THA。