Какова функция 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
тоже.