我有一个元素列表'(a b c),我想找到x是否(真或假)x,例如,x可以是'a或'd。是否有内置功能?
答案 0 :(得分:23)
如果您需要使用等效运算符中的一个进行比较,则可以使用memq
, memv
, or member
,具体取决于您是否要分别使用eq?
, eqv?
, or equal?
查找相等。
> (memq 'a '(a b c))
'(a b c)
> (memq 'b '(a b c))
'(b c)
> (memq 'x '(a b c))
#f
如您所见,如果找到一个元素,这些函数将从第一个匹配元素开始返回子列表。这是因为如果您正在搜索可能包含布尔值的列表,则需要能够区分找到#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兼容的Scheme中实现精确实现的示例理性数字)
如果您需要使用与内置谓词不同的等价谓词搜索列表中的项目,那么您可能需要来自SRFI-1的find
或find-tail
:
> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6))
'(4 5 6)
答案 1 :(得分:3)
这是一种方式:
> (cond ((member 'a '(a b c)) '#t) (else '#f))
#t
> (cond ((member 'd '(a b c)) '#t) (else '#f))
#f
成员返回从元素所在位置开始的所有内容,或#f。 cond用于将其转换为true或false。
答案 2 :(得分:0)
您正在寻找“发现”
基础知识 - 最简单的情况就是(查找条目列表),通常用作谓词:“列表中的条目?”。如果成功找到有问题的元素,它将返回第一个匹配元素而不是“t”。 (取自第二个链接。)
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html
-OR -
答案 3 :(得分:0)
我不知道是否有内置功能,但您可以创建一个:
(define (occurrence x lst)
(if (null? lst) 0
(if (equal? x (car lst)) (+ 1 (occurrence x (cdr lst)))
(occurrence x (cdr lst))
)
)
)
您将获得列表中x
的出现次数。您也可以使用true
或false
进行扩展。
答案 4 :(得分: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