开发者

Generate n unique random integers in ruby / rails

开发者 https://www.devze.com 2022-12-15 03:59 出处:网络
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)

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

0

精彩评论

暂无评论...
验证码 换一张
取 消