Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to sort a hashtable by value?

Tags:

lisp

clisp

Now i have to copy the hastable to a list before sorting it:

(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, what's the better way to fetch the first N elements of a list ?

like image 475
z_axis Avatar asked Sep 22 '11 01:09

z_axis


People also ask

How do you sort a Hashtable by value?

Hashtables are not sorted. So you need to make a copy of the hash table's key set, sort it, and retrieve the values from the hashtable by iterating through the keys in your sorted list. Or use a sorted hash table substitute, such as TreeMap; that would avoid having to make the copy of the key set.

Can you sort a hash table?

Before moving forward, we need to understand that it is not possible to sort a Hashtable since the data is stored by the hashcode of the key, not by the index . So to sort the data of a Hashtable, we need to have a sortable object like an array or an ArrayList. Sorting has to be done on Key or Value.

Can we sort Hashtable in Java?

A Hashtable has no predictable iteration order, and cannot be sorted. If you only want predictable iteration order you should use a LinkedHashMap . If you want to be able to sort your Map , you should use a TreeMap .

Which is faster Hashtable or sorted list?

Unless the hashing algorithm is extremely slow (and/or bad), the hashtable will be faster.


1 Answers

Vatine's answer is technically correct, but probably not super helpful for the immediate problem of someone asking this question. The common case of using a hash table to hold a collection of counters, then selecting the top N items by score can be done like this:

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

The first function returns the contents of a hash table as a series of cons'd pairs in a list, which is called an association list (the typical list representation for key/value pairs). Most Lisp enthusiasts already have a variation of this function on hand because it's such a common operation. This version is from the Alexandria library, which is very widely used in the CL community.

The second function uses SUBSEQ to grab the first N items from the list returned by sorting the alist returned by the first function using the CDR of each pair as the key. Changing :key to #'car would sort by hash keys, changing #'> to #'< would invert the sort order.

like image 102
Jack Rusher Avatar answered Sep 28 '22 04:09

Jack Rusher