如果您可以对您正在处理的文本做出一些假设,那么可能会有更好的可能性来做到这一点。例如,如果您只处理英文文本,那么您可以实现一个非常简单的哈希函数(基本上,使用 128 个元素长的位向量),这样您甚至不需要使用哈希表(即更复杂的结构)。下面的代码说明了这个想法。
(defun string-alphabet (input)
(loop with cache =
(coerce (make-array 128
:element-type 'bit
:initial-element 0) 'bit-vector)
with result = (list input)
with head = result
for char across input
for code = (char-code char) do
(when (= (aref cache code) 0)
(setf (aref cache code) 1
(cdr head) (list char)
head (cdr head)))
finally (return (cdr result))))
(string-alphabet "overflow")
;; (#\o #\v #\e #\r #\f #\l #\w)
强制转换bit-vector
并不是很重要,但它更容易调试(打印形式更紧凑),并且某些实现实际上可能会优化它以仅包含平台需要表示这么多位的这么多整数,即在128 位长度,在 64 位平台上,它可以短至 2 或 3 个整数长。
或者,你也可以这样做,使用整数:
(defun string-alphabet (input)
(loop with cache = (ash 1 128)
with result = (list input)
with head = result
for char across input
for code = (char-code char) do
(unless (logbitp code cache)
(setf cache (logior cache (ash 1 code))
(cdr head) (list char)
head (cdr head)))
finally (return (cdr result))))
但在这种情况下,在最坏的情况下,您将创建 128 个大整数,毕竟这并不昂贵,但位向量可能会做得更好。但是,这可能会给您一个提示,例如,当您可以假设只使用英文字母时(在这种情况下,可以使用比机器记忆字更短的整数)。