2011-09-22 88 views
5

现在我有排序之前将其hastable复制到一个列表:按值排序散列表的最佳方法是什么?

(defun good-red() 
    (let ((tab (make-hash-table)) (res '())) 
    (dotimes (i 33) (setf (gethash (+ i 1) tab) 0)) 
    (with-open-file (stream "test.txt") 
     (loop for line = (read-line stream nil) 
      until (null line) 
      do 
       (setq nums (butlast (str2lst (substring line 6)))) 
       (dolist (n nums) (incf (gethash n tab))) 
       )) 
    **(maphash #'(lambda (k v) (push (cons k v) res)) tab)** 
    (setq sort-res (sort res #'< :key #'cdr)) 
    (reverse (nthcdr (- 33 18) (mapcar #'car sort-res))))) 

顺便说一句,有什么更好的方式来获取列表的第N个元素?

+1

您的问题是什么?标题中的内容,还是内容中的内容? –

+0

仅仅回答标题中的和/或评论中的那一个,会不会更具有建设性? – Paralife

回答

10

Vatine的答案在技术上是正确的,但对于有人提出这个问题的直接问题可能不是很有帮助。使用哈希表来保存计数器的集合,然后选择按分数的前N项的常见情况是可以做到这样的:

;; convert the hash table into an association list 
(defun hash-table-alist (table) 
    "Returns an association list containing the keys and values of hash table TABLE." 
    (let ((alist nil)) 
    (maphash (lambda (k v) 
       (push (cons k v) alist)) 
      table) 
    alist)) 

(defun hash-table-top-n-values (table n) 
    "Returns the top N entries from hash table TABLE. Values are expected to be numeric." 
    (subseq (sort (hash-table-alist table) #'> :key #'cdr) 0 n)) 

第一个函数返回一个哈希表的内容为一系列的缺点'd对在列表中,它被称为关联列表(键/值对的典型列表表示)。大多数Lisp爱好者手头上已经有了这种功能的变体,因为它是如此常见的操作。该版本来自Alexandria库,在CL社区中使用非常广泛。

第二个函数使用SUBSEQ从第一个函数返回的alist中返回的列表中获取第一个N个项目,第一个函数使用每对的CDR作为关键字。更改:#号汽车的钥匙将通过哈希键排序,将#'>更改为#'<将颠倒排序顺序。

2

散列表本质上是无序的。如果你想对它进行排序,你需要用内容初始化某种有序的数据结构。

如果你想获取序列的前N个元素,总是有SUBSEQ。

相关问题