Random key from Ruby Hash (faster)
I found baby's class, but it was not working (at least not in Ruby 1.8.x). I made it work (slight changes), and I added the keys_not_used to make it work faster (baby's random would cycle almost forever on large lists). But I would say all credit should go to the original author, who did all the hard work.
Without further ado, here is the new version:
1 2 class RandomHash < Hash 3 4 @keys_used = nil 5 6 def random_key 7 if @keys_used == nil then 8 @keys_used = Hash.new 9 else 10 @keys_used = Hash.new if @keys_used.size == self.size 11 end 12 13 if (@keys_used.size == 0) then 14 pos = rand(self.size) 15 key = self.keys[pos] 16 else 17 @keys_not_used = Hash.new 18 self.keys.each{ |key| 19 if (! @keys_used.include?(key)) then 20 @keys_not_used[key] = 1 21 end 22 } 23 pos = rand(@keys_not_used.size) 24 key = @keys_not_used.keys[pos] 25 end 26 27 @keys_used[key] = 1 28 return key 29 end 30 end 31 32 # Test code 33 $sources = Hash.new 34 $RandomSources = RandomHash.new 35 36 begin 37 38 (1..10).each{ |val| 39 $sources["#{val}"] = 1 40 } 41 42 $sources.each { |src| 43 puts "Src=#{src}" 44 $RandomSources[src] = 1 45 } 46 47 RandomKeys = Hash.new 48 (0..$sources.length).each{ |index| # one more than all values 49 key = $RandomSources.random_key 50 print "Extracted #{key} ... It's a" 51 if (!RandomKeys.has_key?(key)) then 52 puts " NEW key!" 53 RandomKeys[key] = 1 54 else 55 puts "n OLD key!" 56 end 57 } 58 end