红宝石中的随机范围表示为
rand(2..11)
让我们说我喜欢数字2或该范围内的任何其他数字重复不超过 N 次数。
是这样做的吗?
答案 0 :(得分:2)
我认为没有默认方法可以做到这一点。您需要编写一些代码,例如,请查看Marc Talbot的答案:https://stackoverflow.com/a/9458016/1306709
a = (100..999).to_a.shuffle
然后每次你需要一个新的身份
new_id = a.pop
这可以保证数字永远不会被重用。当然,当你用完阵列上的元素时,你会遇到问题。
所以,如果你需要重复几次 - 将几个具有相似数字的集合和pop
组合起来。
答案 1 :(得分:2)
您可以通过执行以下步骤来完成此操作:
n
个实例,且最多只允许m
,请删除所有n
并添加回m
n-m
值,该数组由初始范围的元素减去有限重复值<强>代码强>
def random_with_limit(range, sample_size, limited_repeat_value, max_instances)
a = Array.new(sample_size) { rand range }
extra = a.count(limited_repeat_value) - max_instances
puts "inital number of #{limited_repeat_value} = #{max_instances+extra}"
return a if extra <= 0
b = [*range]-[limited_repeat_value]
(a-[limited_repeat_value]).
concat([limited_repeat_value]*max_instances).
concat(Array.new(extra) { b.sample }).
shuffle
end
puts
声明仅供参考。
<强>实施例强>
我已经创建了一个帮助器,用于显示随机选择的范围中每个元素的数量。此方法还会在初始无限制样本中打印指定元素的实例数。
def show_result(range, sample_size, limited_repeat_value, max_instances)
random_with_limit(2..11, 50, 4, 3).sort.chunk(&:itself).map { |n,dups|
"#{n} (#{dups.count})" }
end
show_result(2..11, 50, 4, 3)
# inital number of 4 = 4
#=> ["2 (6)", "3 (10)", "4 (3)", "5 (5)", "6 (5)",
# "7 (6)", "8 (5)", "9 (2)", "10 (6)", "11 (2)"]
show_result(2..11, 50, 4, 3)
# inital number of 4 = 3
#=> ["2 (7)", "3 (5)", "4 (3)", "5 (3)", "6 (4)",
# "7 (6)", "8 (5)", "9 (6)", "10 (7)", "11 (4)"]
show_result(2..11, 50, 4, 3)
# inital number of 4 = 2
#=> ["2 (5)", "3 (5)", "4 (2)", "5 (4)", "6 (8)",
# "7 (8)", "8 (1)", "9 (7)", "10 (4)", "11 (6)"]
show_result(2..11, 50, 4, 3)
# inital number of 4 = 7
#=> ["2 (2)", "3 (8)", "4 (3)", "5 (8)", "6 (5)",
# "7 (3)", "8 (3)", "9 (6)", "10 (5)", "11 (7)"]
替代方法
n > m
,请随意选择n-m
n-m
个选定索引处的值替换为第一个解决方案中选择的随机值
def random_with_limit(range, sample_size, limited_repeat_value, max_instances)
a = Array.new(sample_size) { rand range }
extra = a.count(limited_repeat_value) - max_instances
puts "inital number of #{limited_repeat_value} = #{max_instances+extra}"
return a if extra <= 0
idx = a.each_with_index.select { |x,_| x == limited_repeat_value }.map(&:last)
b = [*range]-[limited_repeat_value]
idx.shuffle.first(extra).each { |i| a[i] = b.sample }
a
end
show_result(2..11, 50, 4, 3)
# inital number of 4 = 6
# => ["2 (2)", "3 (3)", "4 (3)", "5 (4)", "6 (7)",
# "7 (12)", "8 (4)", "9 (7)", "10 (5)", "11 (3)"]
show_result(2..11, 50, 4, 3)
# inital number of 4 = 2
#=> ["2 (9)", "3 (3)", "4 (2)", "5 (6)", "6 (6)",
# "7 (3)", "8 (2)", "9 (5)", "10 (9)", "11 (5)"]
show_result(2..11, 50, 4, 3)
# inital number of 4 = 4
#=> ["2 (3)", "3 (3)", "4 (3)", "5 (5)", "6 (4)",
# "7 (7)", "8 (6)", "9 (4)", "10 (7)", "11 (8)"]