Какова функция Scheme для поиска элемента в списке?

У меня есть список элементов '(A b c), и я хочу найти, есть ли в нем (true или false) x, где x может быть "a или" d, например. Есть ли встроенная функция для этого?

4 ответов


Если вам нужно сравнить с помощью одного из операторов эквивалентности сборки, вы можете использовать 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

как вы можете видеть, эти функции возвращают подсписок, начиная с первого соответствующего элемента, если они находят элемент. Это связано с тем, что при поиске списка, который может содержать логические значения, необходимо в состоянии различить случай нахождения #f из материалов дела не найти элемент, который вы ищете. Список-это истинное значение (единственное ложное значение в схеме -#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? (это из-за работу со сверхбольшими числами и рациональных чисел, которые могут храниться в стороны таким образом, что они не будут 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

(обратите внимание, что некоторое поведение функций не определено спецификацией и, следовательно, может отличаться от реализации к реализации; я включил примеры, которые должны работать в любом R5RS совместимая схема, реализующая точные рациональные числа)

Если вам нужно искать элемент в списке, используя предикат эквивалентности, отличный от одного из встроенных, то вы можете захотеть 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 используется для преобразования этого в true или false.


вы ищете "найти"

основы-самый простой случай-просто (найти список записей), обычно используемый в качестве предиката: "является ли запись в списке?". Если ему удается найти соответствующий элемент, он возвращает первый соответствующий элемент вместо "t". (взято из второй ссылка на сайт.)

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

или

http://www.apl.jhu.edu / ~hall/Lisp-Notes/Higher-Order.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 или false тоже.