Reputation: 18075
How to iterate over items (keys, values) in Elisp hash-tables?
I created a hash-table (map, dictionary) using (make-hash-table)
and populated it with different items. In Python i could iterate over dicts by:
for k in d # iterate over keys
for k in d.keys() # same
for k in d.values() # iterate over values
for k in d.items() # iterate over tuples (key, value)
How can i do the same the most succinct and elegant way possible, preferably without loop-macro?
Upvotes: 9
Views: 3900
Reputation: 18075
Starting from 2013 there is a third-party library ht
, which provides many convenient functions to operate on Elisp hash-tables.
Suppose you have a hash-table, where keys are strings and values are integers. To iterate over a hash-table and return a list, use ht-map
:
(ht-map (lambda (k v) (+ (length k) v)) table)
;; return list of all values added to length of their keys
ht-each
is just an alias for maphash
. There are also anaphoric versions of the above 2 functions, called ht-amap
and ht-aeach
. Instead of accepting an anonymous function, they expose variables key
and value
. Here's the equivalent expression to the one above:
(ht-amap (+ (length key) value) table)
Upvotes: 2
Reputation: 4426
I would have preferred to put this into a comment, but my reputation rating ironically prevents me from writing this in the appropriate format...
loop
is considered deprecated and so is the cl
library,
because it didn't adhere to the convention of prefixing all symbols by
a common library prefix and thus polluted the obarray with symbols
without clear library association.
Instead use cl-lib
which defines the same functions and macros but
names them e.g. cl-loop
and cl-defun
instead of loop
and
defun*
. If you need only the macros, you can import cl-macs
instead.
Upvotes: 0
Reputation: 8143
maphash
is the function you want. In addition I would suggest you to look at the manual (info "(elisp) Hash Tables")
Upvotes: 3
Reputation:
I'm going to advertise myself a bit, so take it with a grain of salt, but here are, basically, your options:
maphash
- this is the built-in iteration primitive, fundamentally, no more ways to do it exist.
(loop for KEY being the hash-key of TABLE for VALUE being the hash-value of TABLE ...)
is available in cl
package. It will internally use maphash
anyway, but it offers you some unification on top of different iterating primitives. You can use loop
macro to iterate over multiple different things, and it reduces the clutter by removing the technical info from sight.
http://code.google.com/p/i-iterate/ Here's a library I'm working on to provide more versatile ways of iterating over different things and in different ways in Emacs Lisp. It is inspired by Common Lisp Iterate library, but it departed from it quite far (however, some basic principles still hold). If you were to try this library, the iteration over the hash-table would look like this: (++ (for (KEY VALUE) pairs TABLE) ...)
or (++ (for KEY keys TABLE) ...)
or (++ (for VALUE values TABLE) ...)
.
I will try to describe cons and pros of using either cl
loop
or i-iterate
.
loop
, iterate allows iterating over multiple hash-tables at once (but you must be aware of the additional cost it incurs: the keys of the second, third etc. hash-tables must be collected into a list before iterating, this is done behind the scenes).cl
library.Just as an aside, the full version of the iterate on hash-tables looks like this: (for VAR pairs|keys|values TABLE &optional limit LIMIT)
, where LIMIT
stands for the number of element you want to look at (it will generate more efficient code, then if you were to break from the loop using more general-purpose tools).
Upvotes: 9
Reputation: 21517
(maphash (lambda (key value) ....your code here...) hash-table)
Upvotes: 16