我有一个元素列表'(abc),我想找出其中是否(真或假)x,其中x可以是'a或'd,例如。是否有内置功能?
5 回答
如果您需要使用内置等效运算符之一进行比较,则可以使用memq
、memv
或member
,具体取决于您是否要分别使用 、 或 来查找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
例如、、或表达式。memv
member
if
cond
and
or
> (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 兼容方案中工作的示例)
如果您需要使用与内置谓词不同的等价谓词在列表中搜索项目,那么您可能需要find
或find-tail
来自 SRFI-1:
> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6))
'(4 5 6)
这是一种方法:
> (cond ((member 'a '(a b c)) '#t) (else '#f))
#t
> (cond ((member 'd '(a b c)) '#t) (else '#f))
#f
member 返回从元素所在位置或#f 开始的所有内容。cond 用于将其转换为真或假。
您正在寻找“发现”
基础知识 - 最简单的情况就是(查找条目列表),通常用作谓词:“条目是否在列表中?”。如果成功找到有问题的元素,它会返回第一个匹配的元素,而不仅仅是“t”。(取自第二个链接。)
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html
-或者-
我不知道是否有内置函数,但您可以创建一个:
(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
。
(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