发布
社区首页 >问答首页 >具有构造密钥的高效哈希表访问

具有构造密钥的高效哈希表访问
EN

Stack Overflow用户
提问于 2016-12-04 22:13:26
回答 1查看 318关注 0票数 1

公共Lisp允许任何lisp对象充当哈希表键。但是,如果您只想使用对象的一部分作为键呢?例如,在

代码语言:javascript
代码运行次数:0
复制
(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的子结构,并使用该子结构作为键,但这似乎有点特别,只是为了访问哈希表。还有其他方法可以更好地发挥作用吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-13 16:39:05

我将使用来自这里的通用Lisp库,例如

cl-自定义哈希表

然后转到您的代码,首先当您创建这样的操作时:

代码语言:javascript
代码运行次数:0
复制
CL-USER>  (setq action-1 (make-action 
   :parameters '(1 2 3) 
   :time 45))

产生此错误:

代码语言:javascript
代码运行次数:0
复制
The value NIL is not of the expected type HASH-TABLE.
   [Condition of type TYPE-ERROR]

因此,您需要将您的定义更改为这样的内容:

代码语言:javascript
代码运行次数:0
复制
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>)

然后,您应该定义一个相同时间的函数,或者任何您需要的函数,如下所示:访问数据

代码语言:javascript
代码运行次数:0
复制
CL-USER> (action-time action-1)
45

创建另一个动作

代码语言:javascript
代码运行次数:0
复制
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>)

创建测试功能

代码语言:javascript
代码运行次数:0
复制
CL-USER> (defun equal-actions-by-time (a1 a2) (= (action-time a1) (action-time a2)))
EQUAL-ACTIONS-BY-TIME

定义散列函数:

代码语言:javascript
代码运行次数:0
复制
CL-USER> (defun hash-action (a) (action-time a))
HASH-ACTION

创建您的哈希

代码语言:javascript
代码运行次数:0
复制
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*

试一试:

代码语言:javascript
代码运行次数:0
复制
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情况下,您可以按照以下方式工作:

代码语言:javascript
代码运行次数:0
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40964319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档