Lisp 当键是字符串时,我可以使用assoc吗?

Lisp 当键是字符串时,我可以使用assoc吗?,lisp,common-lisp,Lisp,Common Lisp,我有这样一个数据集:”((“红色”35)(“蓝色”68)…) 当键是字符串时,是否可以使用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

我有这样一个数据集:
”((“红色”35)(“蓝色”68)…)

当键是字符串时,是否可以使用
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


取决于您是否希望比较区分大小写。

正如其他人所指出的,您可以使用不同类型的键,如中所述:

? (assoc "foot" ggg :test #'equalp)
("foot" 2)

如果确定列表仅包含字符串,则可以使用特定于类型的函数
string=
(区分大小写)或
string equal
(不区分大小写)

但是,这些函数也接受符号以及符号和字符串的混合

因此
(assoc“ABC”list:test#'string=)
不仅会找到键
“ABC”
,还会找到名称为
“ABC”
的任何符号,例如符号
:ABC
cl use:ABC
mypackage:ABC

用于比较任意两个对象的通用
equal
equalp
函数不具有此行为。与上述两个类似,
equal
equalp
分别区分大小写和不区分大小写。然而,他们也比较其他种类的物体

不同于<代码> String=和字符串相等< /代码>,<代码>相等< /代码>和<代码>均衡器< /代码>不考虑字符串和符号等价;也就是说,

(equalp“FOO”'FOO)->nil
。它们也不考虑具有相同名称的符号:<代码>(均衡器Fo:FoO)-> nIL/COD>。当两个参数都是符号时,
equal
equalp
应用与
eq
函数相同的测试

因此,我认为,对关联列表进行适当的测试,因为您混合了字符串键和符号键,是两个函数
equal
equalp
中的一个

这些函数还允许您的列表具有其他类型的键,如数字
equalp
将按值比较数字,因此1和1.0是相同的键,而
equal
更紧。这两个函数都递归到列表中。列表
(12)
(12)
是相等的,即使它们不是同一个对象(单独使用),而
(12)
(12.0)
不是相等的,而是相等的(除非你有一个非常奇怪的浮点系统)。此外,向量对象不是通过
equal
逐元素进行比较,而是通过
equalp
进行比较

即使列表中只有字符串,也最好使用这两个函数。 您不会得到太多(如果有的话)性能方面的好处
string=
仍然需要验证参数的类型,以确保它们是受支持的类型,并根据参数的字符串和符号组合进行调度
equal
根据多种类型的可能性进行调度,但这可以有效地完成

在Lisp中,习惯性地使用过度特定于类型的函数或不适当地严格相等是一种糟糕的做法

string=
故意使用,但不是为了保存机器循环,而是在必须将符号作为字符串或符号与字符串的混合进行比较的情况下使用。例如,如果您正在实现
循环
宏,则可以使用
字符串=
来检测
循环
子句单词,根据ANSI Common Lisp规范,这些单词根据符号名称被视为等价的。用户可以编写
(循环:对于42以下的x…
(循环mypackage:对于42以下的x…
)。但是
(循环“FOR…”)
无效!所以你不能只依靠
string=
;您必须验证子句单词是否是符号


请参阅
:TEST
关键字参数。
(assoc "foot" ggg :test #'string=)
? (assoc "foot" ggg :test #'equalp)
("foot" 2)
(setq alist '(("one" . 1)("two" . 2))) =>  (("one" . 1) ("two" . 2))
(assoc "one" alist) =>  NIL
(assoc "one" alist :test #'equalp) =>  ("one" . 1)