Im trying to generate n unique random numbers be开发者_运维百科tween 1 and max
I tried the following code but doesn't work (returns repeated numbers)
r = [ ]
n.times { v = rand(max) while r.include? v ; r << v}
Whats wrong with it? Thanks
added:
max is thousands
n is 10
No, no, don't generate randomly and then check, generate the uniq numbers and then sort randomly!
(1..max).sort_by{rand}
Or, in 1.9:
(1..max).to_a.shuffle
I think your while r.include logic is the wrong way around. Try this:
r = [ ]
while r.length < n
v = rand(max)
r << v unless r.include? v
end
Note that this will go into an infinite loop if max < n.
Kernel#rand
generates a pseudorandom number. This should cause concern if security is an issue.
In Rails use ActiveSupport::SecureRandom.random_number
Also both Kernel#rand
and ActiveSupport::SecureRandom.random_number
may return 0, you say the value must be between 1 and max.
I would suggest to use hash rather than array, because the complexity to compare a number in Array is array.length while in hash it's 1. And you can finally transfer hash keys into an array.
hash = {} r = [ ]
while hash.length < n
a = rand(max)
if !hash_has_key? (a)
hash(a) = :ok
end
end
r = hash.keys
if you test n=30000 and max = 500000, the time consumed is very different compared with using array.
I am not sure of the exact ruby syntax, but as an algorithm:
list = [1 .. 10000];
nums = [];
while (nums.length < needed) {
nums.push( list.splice(rand() * list.length) )
}
should work fairly well, so long as your range isn't too big and won't need to waste time shuffling the entire list
精彩评论