Re: Getting a random hash-table element?





Tonci Damjanic wrote:
On Wed, 28 Nov 2007 03:13:41 +0100, Tonci Damjanic wrote:


<cut>


Thank you all for your advices, some of them evolved into something more
complicated than I had in my mind.

I've taken Ken's advice (the first one) and coded something like this:

(defun get-random-element ()
(let (position)
(setf position (random (hash-table-count *my-table*)))
(find-selected-symbol position)))

The nice thing about every form returning a value is:

(find-selected-symbol
(random (hash-table-count *my-table*)))

But we get more mileage out of code when it is parameterized. Sure, you could rebind the special before each call and sometimes that is appropriate (when other wise you are just forever having to pass the table around) but by default I'd like to see a parameter:

(defun gre (h)
(fss (random (hash-table-count h))))

As for fss...


(defun find-selected-element (n)
(let (result)
(maphash #'(lambda (k v)
(declare (ignore v))
(if (= n 0) (progn
(setf result k)
(decf n))
(decf n)))
*my-table*)
result))

It's a bit ugly, but it works fine... :)

Yep, and I like the counting down and testing for zero instead of counting up with a second variable.

When you are ready (and don't wait too long) learn loop:

(defun gre-fss (h)
(loop for x downfrom (random (hash-table-count h))
for v being the hash-values of h
when (zerop x) return v))


kt

--
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
.