我正在使用Emacs Lisp,但是已经cl加载了包,用于一些常见的lisp功能.
我有一个包含多达50K条目的哈希表,整数键映射到三元组,类似这样(但在实际的lisp中):
{
  8   => '(9  300 12)
  27  => '(5  125 9)
  100 => '(10 242 14)
}
Run Code Online (Sandbox Code Playgroud)
三元组中的第二个值是在构建散列表的复杂算法期间计算的分数.我需要收集一个常规的lisp列表,其中包含哈希中的所有键,按得分排序(即由值的cadr排序的所有键).
所以对于上面的内容,我需要这个列表:
'(27 100 8)
Run Code Online (Sandbox Code Playgroud)
我目前正在做两个阶段,感觉效率低于它需要的阶段.
有没有办法做到这一点?
我当前的解决方案用于maphash将密钥和值收集到两个新列表中,然后sort以正常方式执行,参考谓词中的分数列表.但是,我觉得我可以将收集和排序结合起来.
编辑| 我也不依赖于使用哈希表,尽管我确实需要对整数键的持续访问时间,这些键不是线性间隔的.
编辑2 | 看起来实现二叉树排序可能会起作用,树中的标签是分数,值是键......这样我就可以在哈希映射时进行排序.
...继续阅读有关排序算法的维基百科页面
基本上,您的解决方案是正确的:您需要将密钥收集到列表中:
(defun hash-table-keys (hash-table)
  (let ((keys ()))
    (maphash (lambda (k v) (push k keys)) hash-table)
    keys))
Run Code Online (Sandbox Code Playgroud)
然后对列表进行排序:
(sort (hash-table-keys hash-table)
      (lambda (k1 k2)
        (< (second (gethash k1 hash-table))
           (second (gethash k2 hash-table)))))
Run Code Online (Sandbox Code Playgroud)
可以将密钥集合与排序相结合:您需要将密钥收集到树中,然后"展平"树.但是,只有在处理真正庞大的表时,这才有意义.此外,由于Emacs Lisp编译为字节码,您可能会发现使用sort内置函数仍然比使用树更快.还要考虑开发成本 - 您需要编写其价值主要是教育性的代码.
深入研究,收集密钥会分配密钥列表(结果肯定需要这些密钥),并且sort"就地"操作,因此"简单方法"就像它一样好.
"树"方式将分配树(与所需的键列表相同的内存占用量),填充和展平它将O(n*log(n))与"收集+排序"方式相同.然而,保持树平衡,然后"就地"扁平化(即,不分配新列表)并不是一个简单的练习.
底线是:KISS.
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           592 次  |  
        
|   最近记录:  |