Is there an equivalent to `Array::sample` for hashes?

19,740

Solution 1

Hash[original_hash.to_a.sample(n)]

For Ruby 2.1,

original_hash.to_a.sample(n).to_h

Solution 2

I don't know of such method. Still you can do something like:

h[h.keys.sample]

If you need to sample more than one element the code will have to be a bit more complicated.

EDIT: to get key value pairs instead of only the value you can do something like:

keys_sample = h.keys.sample(n)
keys_sample.zip(keys_sample.map{|k| h[k])

Solution 3

Reading the top ranked answers, I'd go with it depends:

  1. If you want to sample only one element from the hash, @Ivaylo Strandjev's solution only relies on hash lookup and Array#sample:

    hsh[hsh.keys.sample]
    
  2. To sample multiple hash elements, @sawa's answer leverages Array#to_h:

    hsh.to_a.sample(n).to_h
    

Note that, as @cadlac mentions, hsh.to_a.sample.to_h won't work as expected. It will raise

TypeError: wrong element type String at 0 (expected array)

because Array#sample in this case returns just the element array, and not the array containing the element array.

A workaround is his solution, providing an n = 1 as an argument:

hsh.to_a.sample(1).to_h

PS: not looking for upvotes, only adding it as an explanation for people newer to Ruby.

Solution 4

If your sample has only one element, you could use this:

sample = h.keys.sample
h.select { |k,v| k == sample }

Or if your sample contains more than one element, use this:

n = 2
sample = h.keys.sample(n)
h.select { |k,v| sample.include?(k) }
Share:
19,740

Related videos on Youtube

ryanVincent
Author by

ryanVincent

Updated on June 15, 2022

Comments

  • ryanVincent
    ryanVincent about 2 years

    I'm looking to extract n random key-value pairs from a hash.

    • PJP
      PJP over 11 years
      It would help if you'd show a sample of the input hash and explain a bit more what you are attempting to use it for. Grabbing random key/value pairs from a hash is rarely useful, except maybe for testing with random inputs to something, from a known set. It's a very odd request in my experience and makes me think something's wonky.
    • appleLover
      appleLover about 10 years
      i have this same need. i have a hash of hashes, it could also have been stored as an array of hashes. and it makes sense to be able to grab n random entries from an array.
  • PJP
    PJP over 11 years
    This doesn't return a key-value pair as the OP wanted, only the value for a random key.
  • Ivaylo Strandjev
    Ivaylo Strandjev over 11 years
    @theTinMan true. Point taken. Truth is sawa's solution is the neatest solution for that problem
  • PJP
    PJP over 11 years
    If the h has only one element, then use = h. Anything else is overkill.
  • fbonetti
    fbonetti over 11 years
    I said if the sample only has one element. My example assumes a hash with more than one key-value pair. There would be no point in sampling a hash with one element...
  • appleLover
    appleLover about 10 years
    is this slow, or a bad idea, if i am grabbing data from a bigger size hash? would there be an alternate approach to attempt then?
  • sawa
    sawa about 10 years
    @appleLover I can't think of anything better.
  • cadlac
    cadlac about 10 years
    I was curious so I benchmarked it... in case anyone else is curious gist.github.com/bendyorke/924612cba7432cbf36dd
  • whodini9
    whodini9 over 6 years
    Depending on your format, hsh[hsh.keys.sample].keys might also be the solution, if you are looking for sub keys under a particular hash key. For example a users['John Doe'] = user_hash not sure if there is a more 'ruby' way to do this.