List 具有隐式顺序lisp的平面无序列表和元组
Lisp中是否有一个函数与List 具有隐式顺序lisp的平面无序列表和元组,list,data-structures,lisp,common-lisp,List,Data Structures,Lisp,Common Lisp,Lisp中是否有一个函数与assoc处理关联列表的方式相同,但用于平面有序列表和一组具有隐式排序的元组?例如,我有一个平面无序列表和一个查找函数: (defparameter *data2* '((alf age 55 year 2 course lisp) (sue age 22 year 3 course java) (ralf age 16 year 1 course lisp)
assoc
处理关联列表的方式相同,但用于平面有序列表和一组具有隐式排序的元组?例如,我有一个平面无序列表和一个查找函数:
(defparameter *data2* '((alf age 55 year 2 course lisp)
(sue age 22 year 3 course java)
(ralf age 16 year 1 course lisp)
(alf age 8 year 2 course lisp)))
(defun lookup (name course data)
(cdr (assoc name (cdr (assoc course data)))))
这样调用时,查找
函数类似于:
(lookup 'alf 'course *data*) ==> get lisp
现在,使用“具有隐式顺序的元组”(即,值始终以相同顺序排列的值列表):
对于关联列表,是否有任何函数的工作方式与
assoc
相同,但对于平面无序列表和具有隐式顺序的元组?我不确定是否完全理解您的意思;像这样的
(defun lookup (name attr data)
(mapcar (lambda (x) (cadr (member attr x)))
(remove-if-not (lambda (x) (eq name (car x))) data)))
然后
另一个例子是:
(defun lookup (name attr data)
(mapcar (lambda (x) (nth attr x))
(remove-if-not (lambda (x) (eq name (car x))) data)))
然后
不知道我是否完全理解你;像这样的
(defun lookup (name attr data)
(mapcar (lambda (x) (cadr (member attr x)))
(remove-if-not (lambda (x) (eq name (car x))) data)))
然后
另一个例子是:
(defun lookup (name attr data)
(mapcar (lambda (x) (nth attr x))
(remove-if-not (lambda (x) (eq name (car x))) data)))
然后
这个答案有两个部分。首先,如果您试图访问表单
(key1-value1-key2-value…
)列表中的值,那么应该知道这样的列表有一个特殊的名称;它们被称为属性列表,Common Lisp包含一些用于处理它们的函数。其次,如果您不希望列表中包含键,则可以通过使用defstruct
和:type list
来获得大量所需内容。它将定义使用这些隐式结构所需的必要函数
财产清单
其他一些答案描述了如何做到这一点,并使用了函数getf
,但没有一个答案明确说明这种结构有一个名称,即:
属性列表n。1.包含偶数个元素的列表
是交替的名称(有时称为指示符或键)和值
(有时称为属性)。当有多个名称和
属性列表中具有相同名称的值对,第一个
对确定属性。2.(指符号)符号的组成部分
包含属性列表的符号
data2变量是一个关联列表,将名称alf
,sue
等映射到属性列表(年龄55岁2岁…
,(年龄22岁3岁…
)等:
(defparameter *data2* '((alf age 55 year 2 course lisp)
(sue age 22 year 3 course java)
(ralf age 16 year 1 course lisp)
(alf age 8 year 2 course lisp)
))
你想去哪里
(lookup 'alf 'course *data2*)
;=> lisp
您可以使用获取alf的属性列表
(cdr (assoc 'alf *data2*))
;=> (age 55 year 2 course lisp)
然后检索课程:
(getf (cdr (assoc 'alf *data2*)) 'course)
;=> lisp
getf
也可以为列表中没有值的情况提供默认值:
(getf (cdr (assoc 'alf *data2*)) 'favorite-color 'blue)
;=> blue
您还可以将setf
与getf
一起使用:
(setf (getf (cdr (assoc 'alf *data2*)) 'course) 'scheme)
;=> scheme
*data2*
;=> ((alf age 55 year 2 course scheme)
; (sue age 22 year 3 course java)
; (ralf age 16 year 1 course lisp)
; (alf age 8 year 2 course lisp))
注意:由于*data2*
的值是由quote
生成的文本,因此修改它的结果在技术上是未定义的。在这种情况下,它可能会起作用,但一般来说,不要修改文字数据
带的Defstruct:类型列表
在CommonLisp中,可以使用定义简单的记录类型。默认情况下,这些创建的结构可能具有相当高的内存效率(较低的存储开销和恒定的时隙访问)。但是,您可以将:type list
选项指定为defstruct
,以使结构以列表的形式实现。例如:
(defstruct (person (:type list))
name
age
course
year)
这会自动为您定义许多函数。例如,一个是makeperson
:
(make-person :name 'alf
:age 55
:year 2
:course 'lisp)
;=> (alf 55 lisp 2)
(person-age (make-person :name 'alf :age 55 :year 2 :course 'lisp))
;=> 55
(person-year '(alf 55 lisp 2))
;=> 2
其他的是访问器。它们(默认情况下)以结构名称和连字符作为前缀。例如,person-age
和person-year
从一个人那里检索年龄和年份时段的值。这些实际上只是对应列表函数的别名(第二个和第三个),因此它们可以处理具有正确结构的列表,即使它们不是用make person
创建的:
(make-person :name 'alf
:age 55
:year 2
:course 'lisp)
;=> (alf 55 lisp 2)
(person-age (make-person :name 'alf :age 55 :year 2 :course 'lisp))
;=> 55
(person-year '(alf 55 lisp 2))
;=> 2
现在,您可以使用find
从您的*data3*
中按姓名检索一个人(请注意,您将课程和年份的顺序从*data2*
更改为*data3*
):
您可以使用person-*
函数获取值:
(person-year (find 'sue *data3* :key 'person-name))
;=> 3
当然,做一些像
(lookup 'alf 'course *data*)
您需要知道符号课程
对应于函数个人课程
。您可以创建一个哈希表或另一个关联或属性列表来跟踪这些内容。另一种有点笨拙的方法是取课程的符号名,即“课程”
,将“PERSON-”
与之连接,并对其进行实习,以获得符号PERSON-course
,然后您可以与该人进行函数调用。即:
(defun lookup (name slot-name data)
(funcall (intern (concatenate 'string "PERSON-" (symbol-name slot-name)))
(find name data :key 'person-name)))
(lookup 'alf 'course *data3*)
;=> lisp
注意:为了使符号插入更加健壮,我们应该确实确保将符号插入到插入访问者名称的包中,并考虑可读的大小写问题。例如,我们可以执行(intern(连接'string(symbol name'#:person-)(symbol name slot name))(symbol包'make person))
。(当然,有更好的方法可以获得软件包。)这个答案有两个部分。首先,如果您试图访问表单(key1-value1-key2-value…
)列表中的值,那么应该知道这样的列表有一个特殊的名称;它们被称为属性列表,Common Lisp包含一些用于处理它们的函数。其次,如果您不希望列表中包含键,则可以通过使用defstruct
和:type list
来获得大量所需内容。它将定义使用这些隐式结构所需的必要函数
财产清单
其他一些答案描述了如何做到这一点,并使用了函数getf
,但没有一个答案明确说明这种结构有一个名称,即:
属性列表n。1.包含偶数个元素的列表
是交替的名称(有时称为指示器或键)和val
(defun lookup (name slot-name data)
(funcall (intern (concatenate 'string "PERSON-" (symbol-name slot-name)))
(find name data :key 'person-name)))
(lookup 'alf 'course *data3*)
;=> lisp