Emacs – Retrieve key from the hash table and effectively sorted values

I’m using Emacs Lisp, but the cl package is loaded for some common lisp functions.

I have a system with up to 50K entries Hash table, integer keys are mapped to triples, like this (but in the actual lisp):

{
8 =>'(9 300 12 )
27 =>'(5 125 9)
100 =>'(10 242 14)
}

The second value in the triple is in The score calculated during the complex algorithm of building the hash table. I need to collect a regular lisp list containing all the keys from the hash, sorted by score (i.e. all keys sorted by the cadr of the value).

So for the above content, I need this list:

'(27 100 8)

I am currently doing two stages, I feel The efficiency is lower than the stage it needs.

Is there a way to do this?

My current solution uses maphash to collect keys and values ​​into two new lists, and then sort them in the normal way, referring to the score list in the predicate. However, I think I can collect and sort Combine it.

Edit|I also don’t rely on the use of hash tables, although I do need continuous access time to integer keys, which are not linearly spaced.

Edit 2 |It seems that implementing binary tree sorting may work. The tags in the tree are scores and the values ​​are keys… so that I can sort during hash mapping.

…Continue to read the wiki about sorting algorithms Encyclopedia page

Basically, your solution is correct: you need to collect the key to In the list:

(defun hash-table-keys (hash-table)
(let ((keys ()))
( maphash (lambda (kv) (push k keys)) hash-table)
keys))

Then sort the list:

 (sort (hash-table-keys hash-table)
(lambda (k1 k2)
(< (second (gethash k1 hash-table))
(second (gethash k2 hash-table )))))

You can combine key collection with sorting: you need to collect keys into a tree, and then “flatten” the tree. However, only when dealing with really huge tables, This makes sense. Also, since Emacs Lisp is compiled to bytecode, you may find that using built-in sorting is still faster than using trees. Also consider development costs-you need to write code whose value is primarily educational.

Deep research, collecting keys will distribute key lists (the result will definitely need these keys), and the sorting operation is “in-place”, so the “simple method” is as good as it gets.< /p>

The “tree” method will allocate the tree (the same memory footprint as the required key list), and filling and flattening it will be the same O(n * log(n) as the “collection sort” method ) Process. However, keeping the tree balanced and then flattening it “in-place” (i.e., not assigning a new list) is not a simple Practice.

The bottom line is: KISS.

I am using Emacs Lisp, but the cl package is loaded for some common lisp functions.

I have a hash table with up to 50K entries, with integer keys mapped to triples, something like this (but in the actual lisp):

< /p>

{
8 =>'(9 300 12)
27 =>'(5 125 9)
100 =>'(10 242 14)
}

The second value in the triple is the score calculated during the construction of the complex algorithm of the hash table. I need to collect a regular lisp list that contains all the keys from the hash, press Score sorting (that is, all keys sorted by the value of cadr).

So for the above content, I need this list:

'(27 100 8)

I am currently doing two stages, and I feel that the efficiency is lower than the stage it needs.

Is there a way to do this?

My current solution uses maphash to collect keys and values ​​into two new lists, and then sort them in the normal way, referring to the score list in the predicate. However, I think I can collect and sort Combine it.

Edit|I also don’t rely on the use of hash tables, although I do need continuous access time to integer keys, which are not linearly spaced.

Edit 2 |It seems that implementing binary tree sorting may work. The tags in the tree are scores and the values ​​are keys… so that I can sort during hash mapping.

…Continue to read the wiki about sorting algorithms Encyclopedia page

Basically, your solution is correct: you need to collect the key in a list:

(defun hash-table-keys (hash-table)
(let ((keys ()))
(maphash (lambda (kv) (push k keys)) hash-table)
keys))

Then sort the list:

(sort (hash-table-keys hash-table) 
(lambda (k1 k2)
(< (second (gethash k1 hash-table))
(second (gethash k2 hash-table))))))

It is possible to combine key collection with sorting: you need to collect the keys into a tree and then “flatten” the tree. However, this only makes sense when dealing with really huge tables. Also, since Emacs Lisp is compiled as Bytecode, you may find that using built-in sorting is still faster than using trees. Also consider the development cost-you need to write code whose value is mainly educational.

Deep research and collect keys A list of distribution keys​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ Tree (the same memory footprint as the required key list), and filling and flattening it will be an O(n * log(n)) process in the same way as the “collection sort”. However, keep the tree balanced, and then “just Flattening (that is, not assigning a new list) is not a simple exercise.

The bottom line is: KISS.

Leave a Comment

Your email address will not be published.