Какова функция 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
или
Я не знаю, есть ли встроенная функция, но вы можете создать ее:
(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 тоже.