如何在保持数组长度为5
的同时确保此数组的唯一性?
def fixed
5.times.collect { SecureRandom.random_number(10) }
end
这种行为似乎很奇怪:
5.times.collect.uniq { SecureRandom.random_number(10) }
# => [0, 2, 3, 4]
5.times.collect.uniq { SecureRandom.random_number(10) }
# => [0, 1, 3]
5.times.collect.uniq { SecureRandom.random_number(10) }
# => [0, 1, 2, 3, 4]
5.times.collect.uniq { SecureRandom.random_number(10) }
# => [0, 1, 2, 4]
5.times.collect.uniq { SecureRandom.random_number(10) }
# => [0, 1, 2, 3]
答案 0 :(得分:7)
当可能值的数量很少时(例如您的示例中为10),那么我将生成一个包含所有选项的数组,然后随机选择一个sample
条目:
(0..9).to_a.sample(5)
如果可能值的数量巨大,那么首先生成所有值肯定不是一个选择。然后我将生成一个随机值,只要数组中没有足够的条目即可:
require 'set'
values = Set.new
until values.length == 5 do
values.add(SecureRandom.random_number(1_000_000))
end
values.to_a
请注意,我正在使用Set
来确保第二个版本中值的唯一性。
答案 1 :(得分:2)
一种方法是生成从
0
到10
的数字范围,然后 然后将它们混洗以获得唯一的随机数。
您可以使用to_a
将该范围转换为Array并使用shuffle
对其进行随机播放
您可以执行以下操作:
(0..10).to_a.shuffle[0..4] # => [8, 6, 1, 9, 10]
[0..4]
将为您提供前5个经过改组的元素。
希望有帮助。
答案 2 :(得分:2)
使用SecureRandom
def fixed
unique_numbers = []
5.times.collect do
loop do
number = SecureRandom.random_number(10)
break number unless unique_numbers.include?(number)
end
end
end
如果要生成1到10之间的唯一数字,则可以创建1到10的数组,并使用shuffle
或sample
来获取随机数。
使用shuffle
> (0...10).to_a.shuffle.take(5)
=> [4, 0, 1, 3, 7]
> (0...10).to_a.shuffle.take(5)
=> [6, 2, 3, 9, 1]
> (0...10).to_a.shuffle.take(5)
=> [9, 2, 5, 8, 4]
> (0...10).to_a.shuffle.take(5)
=> [5, 0, 6, 8, 7]
> (0...10).to_a.shuffle.take(5)
=> [2, 7, 1, 5, 0]
使用sample
> (1..10).to_a.sample(5)
=> [4, 6, 3, 2, 7]
> (1..10).to_a.sample(5)
=> [5, 8, 2, 3, 7]
> (1..10).to_a.sample(5)
=> [2, 5, 6, 1, 3]
> (1..10).to_a.sample(5)
=> [8, 5, 10, 9, 3]
> (1..10).to_a.sample(5)
=> [8, 1, 5, 3, 4]
您还可以将SecureRandom
自定义随机数生成器作为参数传递给sample
> (1..10).to_a.sample(5, random: SecureRandom)
=> [6, 3, 4, 7, 10]
> (1..10).to_a.sample(5, random: SecureRandom)
=> [7, 4, 8, 1, 5]
> (1..10).to_a.sample(5, random: SecureRandom)
=> [8, 3, 9, 5, 10]
> (1..10).to_a.sample(5, random: SecureRandom)
=> [6, 8, 9, 2, 1]
> (1..10).to_a.sample(5, random: SecureRandom)
=> [9, 10, 1, 8, 2]
答案 3 :(得分:2)
出于好奇,使用Enumerable#cycle
无限生成器。
MAX = 10
SIZE = 5
[MAX].cycle.inject(Set.new) do |acc, max|
break acc if acc.size >= SIZE
acc << SecureRandom.random_number(max)
end
#⇒ #<Set: {2, 1, 7, 0, 9}>
,甚至使用通用loop
:
loop.each_with_object(Set.new) do |_, acc|
break acc if acc.size >= SIZE
acc << SecureRandom.random_number(10)
end
#⇒ #<Set: {2, 6, 7, 1, 3}>