# How do I generate a list of n unique random numbers in Ruby?

This is what I have so far:

myArray.map!{ rand(max) }

Obviously, however, sometimes the numbers in the list are not unique. How can I make sure my list only contains unique numbers without having to create a bigger list from which I then just pick the n unique numbers?

**Edit:**
I'd really like to see this done w/o loop - if at all possible.

## Answers

This uses Set:

require 'set' def rand_n(n, max) randoms = Set.new loop do randoms << rand(max) return randoms.to_a if randoms.size >= n end end

(0..50).to_a.sort{ rand() - 0.5 }[0..x]

(0..50).to_a can be replaced with any array. 0 is "minvalue", 50 is "max value" x is "how many values i want out"

of course, its impossible for x to be permitted to be greater than max-min :)

In expansion of how this works

(0..5).to_a ==> [0,1,2,3,4,5] [0,1,2,3,4,5].sort{ -1 } ==> [0, 1, 2, 4, 3, 5] # constant [0,1,2,3,4,5].sort{ 1 } ==> [5, 3, 0, 4, 2, 1] # constant [0,1,2,3,4,5].sort{ rand() - 0.5 } ==> [1, 5, 0, 3, 4, 2 ] # random [1, 5, 0, 3, 4, 2 ][ 0..2 ] ==> [1, 5, 0 ]

##### Footnotes:

It is worth mentioning that at the time this question was originally answered, September 2008, that Array#shuffle was either not available or not already known to me, hence the approximation in Array#sort

And there's a barrage of suggested edits to this as a result.

So:

.sort{ rand() - 0.5 }

Can be better, and shorter expressed on modern ruby implementations using

.shuffle

Additionally,

[0..x]

Can be more obviously written with Array#take as:

.take(x)

Thus, the easiest way to produce a sequence of random numbers on a modern ruby is:

(0..50).to_a.shuffle.take(x)

Just to give you an idea about speed, I ran four versions of this:

- Using Sets, like Ryan's suggestion.
- Using an Array slightly larger than necessary, then doing uniq! at the end.
- Using a Hash, like Kyle suggested.
- Creating an Array of the required size, then sorting it randomly, like Kent's suggestion (but without the extraneous "- 0.5", which does nothing).

They're all fast at small scales, so I had them each create a list of 1,000,000 numbers. Here are the times, in seconds:

- Sets: 628
- Array + uniq: 629
- Hash: 645
- fixed Array + sort: 8

And no, that last one is not a typo. So if you care about speed, and it's OK for the numbers to be integers from 0 to whatever, then my exact code was:

a = (0...1000000).sort_by{rand}