公共Lisp允许任何lisp对象充当哈希表键。但是,如果您只想使用对象的一部分作为键呢?例如,在
(defstruct action
(name nil :type symbol)
(parameters nil :type list)
(time 0 :type fixnum)
(database nil :type hash-table))
时隙不适合于均衡散列情况。使用(部分) lisp对象作为键访问哈希表的好策略是什么?一种方法可能使用类似于(list (action-name act1) (action-parameters act1) (action-database act1))
的密钥,但这似乎相当低效。另一种方法可能只使用三个适当的插槽创建操作defstruct的子结构,并使用该子结构作为键,但这似乎有点特别,只是为了访问哈希表。还有其他方法可以更好地发挥作用吗?
发布于 2016-12-13 16:39:05
我将使用来自这里的通用Lisp库,例如
然后转到您的代码,首先当您创建这样的操作时:
CL-USER> (setq action-1 (make-action
:parameters '(1 2 3)
:time 45))
产生此错误:
The value NIL is not of the expected type HASH-TABLE.
[Condition of type TYPE-ERROR]
因此,您需要将您的定义更改为这样的内容:
CL-USER> (defstruct action
(name nil :type symbol)
(parameters nil :type list)
(time 0 :type fixnum)
(database (make-hash-table) :type hash-table))
ACTION
CL-USER> (setq action-1 (make-action
:parameters '(1 2 3)
:time 45))
#S(ACTION :NAME NIL :PARAMETERS (1 2 3) :TIME 45 :DATABASE #<HASH-TABLE :TEST EQL size 0/60 #x3020012E708D>)
然后,您应该定义一个相同时间的函数,或者任何您需要的函数,如下所示:访问数据
CL-USER> (action-time action-1)
45
创建另一个动作
CL-USER> (setq action-2 (make-action
:parameters '(1 2 3)
:time 102))
#S(ACTION :NAME NIL :PARAMETERS (1 2 3) :TIME 102 :DATABASE #<HASH-TABLE :TEST EQL size 0/60 #x3020012FE58D>)
创建测试功能
CL-USER> (defun equal-actions-by-time (a1 a2) (= (action-time a1) (action-time a2)))
EQUAL-ACTIONS-BY-TIME
定义散列函数:
CL-USER> (defun hash-action (a) (action-time a))
HASH-ACTION
创建您的哈希
CL-USER> (define-custom-hash-table-constructor make-action-hash :test equal-actions-by-time :hash-function hash-action)
MAKE-ACTION-HASH
CL-USER> (defparameter *foo-hash* (make-action-hash) "variable for stackoverflow")
*FOO-HASH*
试一试:
CL-USER> (setf (gethash action-1 *foo-hash*) 1
(gethash action-2 *foo-hash*) 10)
10
CL-USER> (gethash action-1 *foo-hash*)
1
T
如果发行版将在本机支持自定义测试/散列函数的实现中工作,则可以避免使用库,如果不能,则可以使用-定制哈希表。
在optimus情况下,您可以按照以下方式工作:
CL-USER> (defparameter *foo-hash* (make-hash-table :test 'equal-actions-by-time :hash-function 'hash-action))
*FOO-HASH*
CL-USER> (setf (gethash action-1 *foo-hash*) 1
(gethash action-2 *foo-hash*) 10)
10
CL-USER> (gethash action-1 *foo-hash*)
1
T
https://stackoverflow.com/questions/40964319
复制相似问题