我有以下代码:
(setq months '((january 1) (february 2) ...))
我可以使用get
将此列表用作地图(使用键和值)
喜欢:
(get 'months 'january)
得到结果:1
是否可以在Lisp中执行此操作而无需显式设置如下属性:
(setf (get 'months 'january) 1)
(setf (get 'months 'february) 2)
...
如果在Common Lisp中无法做到这一点,是否可以使用Lisp的任何其他方言?
答案 0 :(得分:5)
没有。 documentation for get
表示用法是
获取符号指示符&可选默认值=>值
在属性的符号属性列表中找到属性 指标与指标相同,并返回其对应的指标 适当的价值。如果有多个属性1具有该属性 指标,获得使用第一个这样的属性。如果没有财产 使用该属性指示符,返回默认值。
property list定义为:
属性列表1.包含偶数个元素的列表 是交替的名称(有时称为指标或键)和值 (有时称为属性)。当有多个名字时 在属性列表中具有相同名称的值对,第一个这样 对确定属性。 2.(符号)的组成部分 包含属性列表的符号。
您的数据采用association list:
的形式协会名单代表一个关联的一个conses列表 带有值的键,每个缺点的汽车是键,而cdr是 与该键相关联的值。
因此,您可以使用assoc
访问其中的值。您可以使用属性列表,在这种情况下,如果它不是符号的属性列表,则使用getf
,如果是get
(如上所述),则使用CL-USER> (defparameter *months-alist*
'((january . 1)
(february . 2)
(march . 3)))
*MONTHS-ALIST*
CL-USER> (cdr (assoc 'february *months-alist*))
2
符号的属性列表。以下是所有三种方法的示例。
CL-USER> (defparameter *months-plist*
'(january 1 february 2 march 3))
*MONTHS-PLIST*
CL-USER> (getf *months-plist* 'march)
3
CL-USER> (setf (get '*months* 'january) 1
(get '*months* 'february) 2
(get '*months* 'march) 3)
3
CL-USER> (get '*months* 'january)
1
CL-USER> (defparameter *months-hash* (make-hash-table :test 'eq))
*MONTHS-HASH*
CL-USER> (setf (gethash 'january *months-hash*) 1
(gethash 'february *months-hash*) 2
(gethash 'march *months-hash*) 3)
3
CL-USER> (gethash 'february *months-hash*)
2 ; the value
T ; it was present in the table
当然,您也可以使用哈希映射,或者在订购内容的数据的情况下,您可以找到元素的位置:
CL-USER> (defparameter *months-sequence*
#(january february march april may june july august september))
*MONTHS-SEQUENCE*
CL-USER> (1+ (position 'april *months-sequence*))
4
{{1}}
答案 1 :(得分:-1)
您正在使用a-list作为数据结构来实现关联映射。它具有 O(n)复杂度(线性),因此对于大型地图来说不是一个好的结构。
Common Lisp有一个包含容器的丰富库,可以看到hyperspec,特别是hash-tables。它们可能更相关。如果您认为它们很短(例如使用ASSOC Common Lisp函数),您仍然可以使用a-lists。您还可以考虑B-trees ...