是否可以从给定范围(1-90)中选择一个随机数,但不包括某些数字。排除的数字是动态创建的,但可以说它们分别为3,8和80.
我已设法创建随机数生成器但无法识别任何能够满足我要求的函数。
Random r = new Random();
this.num = r.Next(1, 90);
要排除的数字是先前生成的数字。因此,如果随机数为1,则会将其添加到排除的数字列表中。
答案 0 :(得分:8)
使用一些方便的扩展方法here,您可以创建一系列数字并从该愤怒中随机选择。例如,使用这些扩展方法:
public static T RandomElement(this IEnumerable<T> enumerable)
{
return enumerable.RandomElementUsing(new Random());
}
public static T RandomElementUsing(this IEnumerable<T> enumerable, Random rand)
{
int index = rand.Next(0, enumerable.Count());
return enumerable.ElementAt(index);
}
您可以将这些应用于过滤的数字范围:
var random = Enumerable.Range(1, 90).Except(arrayOfRemovedNumbers).RandomElement();
答案 1 :(得分:5)
创建一个容纳您不想要的数字的容器:
var excludedNumbers = new List<int> { 1, 15, 35, 89 };
然后使用类似的东西:
Random random = new Random();
int number;
do
{
number = r.Next(1, 90);
} while (excludedNumbers.Contains(number));
// number is not in the excluded list now
答案 2 :(得分:4)
可能不是最佳选择,但您可以使用while循环来检查您不想要的数字
Random r = new Random();
this.num = r.Next(1, 90);
do
{
this.num = r.Next(1, 90);
}
while (this.num == 3 || this.num == 8 || this.num == 90);
对于大量数字,您可以使用数组或列表并循环遍历它们
int[] exclude = { 3, 8, 90, 11, 24 };
Random r = new Random();
this.num = r.Next(1, 90);
do
{
this.num = r.Next(1, 90);
}
while (exclude.Contains(this.num));
答案 3 :(得分:3)
您的最新更新,这意味着每个值只能选择一次,这样可以轻松解决问题。
答案 4 :(得分:2)
Random r = new Random();
this.num = r.Next(1, 90);
int excluded[] = new int[] { 3,8,80 }; // list any numbers in this array you want to exclude
for (int i = 0; i < excluded.Length; i++)
{
if (this.num == excluded[i])
{
this.num = r.Next(1, 90); // or you can try doing something else here
}
}
答案 5 :(得分:2)
确保excludedNumbers
为HashSet
以获得最佳效果。
var random = new Random();
var exludedNumbers = new HashSet<int>(new int[] { 3, 8, 80});
var randomNumber = (from n in Enumerable.Range(int.MinValue, int.MaxValue)
let number = random.Next(1, 90)
where !exludedNumbers.Contains(number)
select number).First();
答案 6 :(得分:1)
此解决方案在O(n)最坏的情况下执行此操作,其中n是排除列表和常量内存。代码有点长,但如果您:
可能是相关的它保留了随机分布,因为它实际上会跳过排除列表,并在不包括该集合的范围内生成一个随机数。
这是实施:
private static int RandomInRangeExcludingNumbers(Random random, int min, int max, int[] excluded)
{
if (excluded.Length == 0) return random.Next(min, max);
//array should be sorted, remove this check if you
//can make sure, or sort the array before using it
//to improve performance. Also no duplicates allowed
//by this implementation
int previous = excluded[0];
for (int i = 1; i < excluded.Length; i++)
{
if (previous >= excluded[i])
{
throw new ArgumentException("excluded array should be sorted");
}
}
//basic error checking, check that (min - max) > excluded.Length
if (max - min <= excluded.Length)
throw new ArgumentException("the range should be larger than the list of exclusions");
int output = random.Next(min, max - excluded.Length);
int j = 0;
//set the start index to be the first element that can fall into the range
while (j < excluded.Length && excluded[j] < min) j++;
//skip each number occurring between min and the randomly generated number
while (j < excluded.Length && excluded[j] <= output)
{
j++;
output++;
while (excluded.Contains(output))
output++;
}
return output;
}
测试功能以确保其有效(超过100k元素)
private static void Test()
{
Random random = new Random();
int[] excluded = new[] { 3, 7, 80 };
int min = 1, max = 90;
for (int i = 0; i < 100000; i++)
{
int randomValue = RandomInRangeExcludingNumbers(random, min, max, excluded);
if (randomValue < min || randomValue >= max || excluded.Contains(randomValue))
{
Console.WriteLine("Error! {0}", randomValue);
}
}
Console.WriteLine("Done");
}