什么是在函数列表中查找元素的Scheme函数?

时间:2009-03-29 14:07:54

标签: lisp scheme

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

5 个答案:

答案 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),因此您可以在任何预期的上下文中使用memqmemvmember的结果布尔值,例如ifcondandor表达式。

> (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的findfind-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 -

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

答案 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的出现次数。您也可以使用truefalse进行扩展。

答案 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