2011-09-22 54 views
5

Bây giờ tôi phải sao chép các hastable vào một danh sách trước khi sắp xếp nó:Cách tốt nhất để sắp xếp một hashtable theo giá trị là gì?

(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))))) 

BTW, cách tốt hơn để lấy các yếu tố N đầu tiên của danh sách là gì?

+1

Câu hỏi của bạn là gì? Một trong các tiêu đề, hoặc một trong các nội dung? –

+0

Nó sẽ không mang tính xây dựng hơn để chỉ trả lời câu hỏi trong tiêu đề và/hoặc nhận xét trong phần bình luận? – Paralife

Trả lời

10

Câu trả lời của Vatine là đúng về mặt kỹ thuật, nhưng có lẽ không phải là siêu hữu ích cho vấn đề trước mắt của người nào đó hỏi câu hỏi này. Các trường hợp phổ biến của việc sử dụng một bảng băm để giữ một bộ sưu tập các bộ đếm, sau đó chọn N mục đầu dựa theo chỉ số có thể được thực hiện như thế này:

;; 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)) 

Chức năng đầu tiên trả về nội dung của một bảng băm như một loạt các cons 'd cặp trong danh sách, được gọi là danh sách liên kết (biểu diễn danh sách điển hình cho cặp khóa/giá trị). Hầu hết những người đam mê Lisp đã có một biến thể của chức năng này trên tay bởi vì nó là một hoạt động phổ biến. Phiên bản này là từ thư viện Alexandria, được sử dụng rất rộng rãi trong cộng đồng CL.

Hàm thứ hai sử dụng SUBSEQ để lấy N mục đầu tiên từ danh sách được trả về bằng cách sắp xếp số nguyên được trả về bởi hàm đầu tiên bằng cách sử dụng CDR của mỗi cặp làm khóa. Thay đổi: khóa thành # 'ô tô sẽ sắp xếp theo các khóa băm, thay đổi #'> thành # '< sẽ đảo ngược thứ tự sắp xếp.

2

Bảng băm vốn không có thứ tự. Nếu bạn muốn nó được sắp xếp, bạn cần phải khởi tạo một số loại cấu trúc dữ liệu được sắp xếp với nội dung.

Nếu bạn muốn tìm nạp N phần tử đầu tiên của chuỗi, luôn có SUBSEQ.

Các vấn đề liên quan