Что такое функция Scheme для поиска элемента в списке? - PullRequest
7 голосов
/ 29 марта 2009

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

Ответы [ 4 ]

23 голосов
/ 29 марта 2009

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

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

Если вам нужно искать элемент в списке, используя предикат эквивалентности, отличный от встроенного, то вы можете захотеть find или find-tail от SRFI-1:

> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6))
'(4 5 6)
3 голосов
/ 29 марта 2009

Вот один из способов:

> (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.

0 голосов
/ 16 ноября 2012

Я не знаю, есть ли встроенная функция, но вы можете ее создать:

(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.

0 голосов
/ 29 марта 2009

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

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

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

-или-

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

...