Perl-Sensitive Sunglasses | |
PerlMonks |
Re: easy way to get random key from hash?by grinder (Bishop) |
on Aug 05, 2002 at 19:20 UTC ( [id://187787]=note: print w/replies, xml ) | Need Help?? |
You can do it without an array, but you will still have to pay the cost of scanning all the keys once. The idea is that you choose the first element if rand() < 1 (which it always will be), the second element if rand() < 1/2 (which it will be half of the time), the third element if rand() < 1/3 (which will be one third of the time, which leave 2/3 for the first two elements, and we've already seen that they get chosen 50/50)...
You can see where this is going: choose the nth element if rand() < 1 / n. Translated to Perl this gives something like:
This actually chooses from a list, but then that's what the keys of a hash are, so everything is fine. The beauty of this approach is that you don't need to know beforehand how many elements you have to choose from. That is, the array in question may shrink or grow in the course of the program's run, and the algorithm will compensate. In fact, you may be able to skip loading the hash in the first place, depending on system load. Just read through the file fortune-at-a-time, and cache the file pointer offset instead. Then, at the end of the file seek back to the cached position and read from there. This means you will be able to add fortunes without having to restart the process. I first heard about this technique in a book by Jon Bentley, either _Programming Pearls_ or _More Programming Perls_. They are probably verging on the edge of being out of print, but if you can track them down, they are absolute gems. print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
In Section
Seekers of Perl Wisdom
|
|