8

我有一个元素列表'(abc),我想找出其中是否(真或假)x,其中x可以是'a或'd,例如。是否有内置功能?

4

5 回答 5

26

如果您需要使用内置等效运算符之一进行比较,则可以使用memqmemvmember,具体取决于您是否要分别使用 、 或 来查找eq?相等eqv?equal?

> (memq 'a '(a b c))
'(a b c)
> (memq 'b '(a b c))
'(b c)
> (memq 'x '(a b c))
#f

如您所见,如果这些函数找到元素,则返回从第一个匹配元素开始的子列表。这是因为如果您正在搜索可能包含布尔值的列表,您需要能够区分找到 a#f的情况和未找到您要查找的元素的情况。列表是一个真值(Scheme 中唯一的假值是#f),因此您可以在任何需要布尔值的上下文中使用 、 或 的结果,memq例如、、或表达式。memvmemberifcondandor

> (if (memq 'a '(a b c))
     "It's there! :)"
     "It's not... :(")
"It's there! :)"

三种不同的功能有什么区别?它基于它们用于比较的等价函数。eq?(因此memq)测试两个对象是否是相同的底层对象;它基本上等同于指针比较(或整数情况下的直接值比较)。因此,看起来相同的两个字符串或列表可能不是eq?,因为它们存储在内存中的不同位置。equal?(因此member?)对列表和字符串进行深度比较,因此基本上任何两个打印相同的项目都是equal?. eqv?几乎eq?除了数字之外的任何东西;对于数字,两个数字相等的数字总是eqv?,但它们可能不是eq?(这是因为 bignums 和有理数,它们可能以不同的方式存储eq?

> (eq? 'a 'a)
#t
> (eq? 'a 'b)
#f
> (eq? (list 'a 'b 'c) (list 'a 'b 'c))
#f
> (equal? (list 'a 'b 'c) (list 'a 'b 'c))
#t
> (eqv? (+ 1/2 1/3) (+ 1/2 1/3))
#t

(请注意,规范未定义函数的某些行为,因此可能因实现而异;我已经包含了应该在实现精确有理数的任何 R 5 RS 兼容方案中工作的示例)

如果您需要使用与内置谓词不同的等价谓词在列表中搜索项目,那么您可能需要findfind-tail来自 SRFI-1:

> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6))
'(4 5 6)
于 2009-03-29T15:18:59.587 回答
3

这是一种方法:

> (cond ((member 'a '(a b c)) '#t) (else '#f))
#t
> (cond ((member 'd '(a b c)) '#t) (else '#f))
#f

member 返回从元素所在位置或#f 开始的所有内容。cond 用于将其转换为真或假。

于 2009-03-29T14:23:01.640 回答
0

您正在寻找“发现”

基础知识 - 最简单的情况就是(查找条目列表),通常用作谓词:“条目是否在列表中?”。如果成功找到有问题的元素,它会返回第一个匹配的元素,而不仅仅是“t”。(取自第二个链接。)

http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html

-或者-

http://www.apl.jhu.edu/~hall/Lisp-Notes/Higher-Order.html

于 2009-03-29T14:12:52.600 回答
0

我不知道是否有内置函数,但您可以创建一个:

(define (occurrence x lst)
       (if (null? lst) 0    
            (if (equal? x (car lst))  (+ 1 (occurrence x (cdr lst)))
                                     (occurrence x (cdr lst)) 
            )
       )
) 

Ỳou 将获得x列表中出现的次数作为回报。true你可以用or来扩展它false

于 2012-11-16T17:54:10.110 回答
0
 (define (member? x list)
     (cond ((null? list) #f)
           ((equal? x (car list)) #t)
           (else   (member? x (cdr list)))))

该过程返回 #t (true) 或 #f (false)

(member? 10 '(4 2 3))

输出是#f

于 2020-06-25T16:15:55.647 回答