Могу ли я использовать assoc, когда ключи являются строками?
у меня есть такой набор данных:'(("red" 3 5)("blue" 6 8)...)
можно использовать assoc
когда ключи являются строками? Ни одна из очевидных попыток не сработала для меня в этом простом тесте:
CL-USER> (defparameter ggg (list '("foot" 2) '(bar 5)))
GGG
CL-USER> ggg
(("foot" 2) (BAR 5))
CL-USER> (assoc 'bar ggg)
(BAR 5)
CL-USER> (assoc "foot" ggg)
NIL
CL-USER> (assoc '"foot" ggg)
NIL
CL-USER> (assoc 'foot ggg)
NIL
4 ответов
если вы уверены, что ваш список содержит только строки, вы можете использовать тип функции string=
(с учетом регистра) или string-equal
(без учета регистра).
однако эти функции также принимают символы и смеси символов и строк.
(assoc "ABC" list :test #'string=)
найдет не только ключ "ABC"
, но и любой символ, которого зовут "ABC"
, например, символ :abc
или cl-use:abc
или mypackage:abc
.
универсальный equal
и equalp
функции для сравнение любых двух объектов не имеет такого поведения. Как и вышеупомянутые два, equal
и equalp
, соответственно, чувствительны к регистру и нечувствительны. Однако они также сравнивают другие виды объектов.
в отличие от string=
и string-equal
, equal
и equalp
не считайте строки и символы эквивалентными, то есть (equalp "FOO" 'FOO) -> nil
. Они также не считают эквивалентными символы, имеющие одно и то же имя: (equalp 'foo :foo) -> nil
. Когда оба аргумента являются символами equal
и equalp
применить тот же Тест, что и
(assoc "foot" ggg :test #'string-equal)
или
(assoc "foot" ggg :test #'string=)
в зависимости от того, хотите ли вы сравнение с учетом регистра.
Как уже указывали другие, вы можете использовать различные типы ключей, как описано в HyperSpec:
(setq alist '(("one" . 1)("two" . 2))) => (("one" . 1) ("two" . 2))
(assoc "one" alist) => NIL
(assoc "one" alist :test #'equalp) => ("one" . 1)