From: Mark Carroll
Subject: keys of hash table
Date: 
Message-ID: <UOn*L2n3n@news.chiark.greenend.org.uk>
I can't find an easy way of obtaining a list of the keys of a hash
table in Common Lisp. Can anyone do better than,

(defun keys-of-hash-table (ht)
  (let ((keys nil))
    (labels ((getkey (x y) (push x keys)))
      (maphash #'getkey ht)
      keys)))

Thanks. (-:

-- Mark (too used to Perl's 'keys'!)

From: Stig Hemmer
Subject: Re: keys of hash table
Date: 
Message-ID: <ekvu2rw1lbn.fsf@epoksy.pvv.ntnu.no>
Mark Carroll <·····@chiark.greenend.org.uk> writes:
> (defun keys-of-hash-table (ht)
>   (let ((keys nil))
>     (labels ((getkey (x y) (push x keys)))
>       (maphash #'getkey ht)
>       keys)))

Not really, though there is always the LOOP version:

(defun keys-of-hash-table (ht)
  (loop for key being each hash-key of ht
        collect key))

Incidentally, I have a macro that makes your code a tad more readable:

(defmacro let1 (bindings &body body)
  `(let ,bindings
     ,@body
     ,(if (symbolp (car bindings))
	  (car bindings)
	(car (car bindings)))))

(defun keys-of-hash-table (ht)
  (let1 ((keys nil))
    (labels ((getkey (x y) (push x keys)))
      (maphash #'getkey ht))))

I would probably have written something like

(defun keys-of-hash-table (hash-table)
  (let1 ((keys nil))
    (maphash #'(lambda (key value) (push key keys)) 
             hash-table)))

but that is a matter of taste, I guess.

> -- Mark (too used to Perl's 'keys'!)

Well, you might want to ask yourself if there are other ways of
achieving what you want to do...

Stig Hemmer,
Jack of a Few Trades.
From: Steve Long
Subject: Re: keys of hash table
Date: 
Message-ID: <37740939.9F183E9C@boeing.com>
Stig Hemmer wrote:
> 
> Mark Carroll <·····@chiark.greenend.org.uk> writes:
> > (defun keys-of-hash-table (ht)
> >   (let ((keys nil))
> >     (labels ((getkey (x y) (push x keys)))
> >       (maphash #'getkey ht)
> >       keys)))
> 
> Not really, though there is always the LOOP version:
> 
> (defun keys-of-hash-table (ht)
>   (loop for key being each hash-key of ht
>         collect key))
> 
> Incidentally, I have a macro that makes your code a tad more readable:
> 
> (defmacro let1 (bindings &body body)
>   `(let ,bindings
>      ,@body
>      ,(if (symbolp (car bindings))
>           (car bindings)
>         (car (car bindings)))))
> 
> (defun keys-of-hash-table (ht)
>   (let1 ((keys nil))
>     (labels ((getkey (x y) (push x keys)))
>       (maphash #'getkey ht))))
> 
> I would probably have written something like
> 
> (defun keys-of-hash-table (hash-table)
>   (let1 ((keys nil))
>     (maphash #'(lambda (key value) (push key keys))
>              hash-table)))
> 
> but that is a matter of taste, I guess.
> 
> > -- Mark (too used to Perl's 'keys'!)
> 
> Well, you might want to ask yourself if there are other ways of
> achieving what you want to do...
> 
> Stig Hemmer,
> Jack of a Few Trades.


We were monkeying with tables yesterday. Have written a functions:
(find-in-hash-table value table [:test <test-expr>] [:key <retrieval-expr>])
that returns a list of hash-keys where value is found in table. The only thing
that I do different is to (nreverse keys) before returning them (a real need for
list reversal has yet to arise, though.)  Conditional retrieval of this type is
pretty slow when your table is large (we were working with 13,000 plists)
whether the iteration is done with loop or maphash, so we construct auxilliary
hash-tables with new keys in order to exploit the fast-lookup capability that
drove us to hash-tables in the first place.

I've received a lot of much-appreciated advice, help, and even flames last year
from this ng concerning efficiency but have only come to appreciate it recently
as I've started working with upwards of 10^5 data items at a time.


sl
(better to be a client than a server)
From: Nick Levine
Subject: Re: keys of hash table
Date: 
Message-ID: <7l1r1p$ms2$1@epos.tesco.net>
>We were monkeying with tables yesterday. Have written a functions:
>(find-in-hash-table value table [:test <test-expr>] [:key
<retrieval-expr>])
>that returns a list of hash-keys where value is found in table. The only
thing
>that I do different is to (nreverse keys) before returning them (a real
need for
>list reversal has yet to arise, though.)

I'm intrigued to kow what you think you're gaining from reversing this list
(destructively or otherwise). The implementation is not required to give
them to you in any fixed order. (I'd guess it'll typically be in order of
sxhash value, modulo the local strategy for dealing with keys that hash to
the same value, and with the warning that with an EQ table everything may
change next time the garbage collector runs.)

- n
From: Steve Long
Subject: Re: keys of hash table
Date: 
Message-ID: <37782357.9F16A8A@boeing.com>
Nick Levine wrote:
> 
> >We were monkeying with tables yesterday. Have written a functions:
> >(find-in-hash-table value table [:test <test-expr>] [:key
> <retrieval-expr>])
> >that returns a list of hash-keys where value is found in table. The only
> thing
> >that I do different is to (nreverse keys) before returning them (a real
> need for
> >list reversal has yet to arise, though.)
> 
> I'm intrigued to kow what you think you're gaining from reversing this list
> (destructively or otherwise). The implementation is not required to give
> them to you in any fixed order. (I'd guess it'll typically be in order of
> sxhash value, modulo the local strategy for dealing with keys that hash to
> the same value, and with the warning that with an EQ table everything may
> change next time the garbage collector runs.)
> 
> - n

It accomplishes nothing. I modified the original code to reverse the results
because
the "customer" asked for it: ACL predictably returned hash-keys in an order that
was 
pleasing to them, even after garbage collection. I never relied on it, though,
because
garbage collection is just too mystical of an operation to trust.

sl
From: Marco Antoniotti
Subject: Re: keys of hash table
Date: 
Message-ID: <lwoghzk2pt.fsf@copernico.parades.rm.cnr.it>
Steve Long <··············@boeing.com> writes:

> Nick Levine wrote:
> > 
> > >We were monkeying with tables yesterday. Have written a functions:
> > >(find-in-hash-table value table [:test <test-expr>] [:key
> > <retrieval-expr>])
> > >that returns a list of hash-keys where value is found in table. The only
> > thing
> > >that I do different is to (nreverse keys) before returning them (a real
> > need for
> > >list reversal has yet to arise, though.)
> > 
> > I'm intrigued to kow what you think you're gaining from reversing this list
> > (destructively or otherwise). The implementation is not required to give
> > them to you in any fixed order. (I'd guess it'll typically be in order of
> > sxhash value, modulo the local strategy for dealing with keys that hash to
> > the same value, and with the warning that with an EQ table everything may
> > change next time the garbage collector runs.)
> > 
> > - n
> 
> It accomplishes nothing. I modified the original code to reverse the results
> because
> the "customer" asked for it: ACL predictably returned hash-keys in
> an order that 
> was 
> pleasing to them, even after garbage collection. I never relied on it, though,
> because
> garbage collection is just too mystical of an operation to trust.
> 

Well, at least you can trust that you do not have memory leaks :)

Cheers


-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - 06 68 10 03 17, fax. +39 - 06 68 80 79 26
http://www.parades.rm.cnr.it/~marcoxa
From: Mark Carroll
Subject: Re: keys of hash table
Date: 
Message-ID: <rsq*eSD3n@news.chiark.greenend.org.uk>
Thank you very much! This thread's made very interesting reading.
I even got up the courage to look at 'loop' again. (-:

-- Mark
From: Peter Van Eynde
Subject: Re: keys of hash table
Date: 
Message-ID: <slrn7n715t.9s1.pvaneynd@mail.inthan.be>
On 25 Jun 1999 13:31:18 +0100 (BST), Mark Carroll wrote:
>I can't find an easy way of obtaining a list of the keys of a hash
>table in Common Lisp. Can anyone do better than,
>
>(defun keys-of-hash-table (ht)
>  (let ((keys nil))
>    (labels ((getkey (x y) (push x keys)))
>      (maphash #'getkey ht)
>      keys)))

(defun keys-of-hash-table (ht)
  (loop for key being the hash-keys in ht
        collect key))

Groetjes, Peter

-- 
It's logic Jim, but not as we know it. | ········@debian.org for pleasure,
"God, root, what is difference?" - Pitr| ········@inthan.be for more pleasure!
"God is more forgiving." - Dave Aronson| http://cvs2.cons.org/~pvaneynd