wpf 从范围中选择但排除某些数字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20402067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Select from a range but exclude certain numbers
提问by RSM
Is it possible to pick a random number from a given range (1-90), but exclude certain numbers. The excluded numbers are dynamically created but lets say they are 3, 8, and 80.
是否可以从给定范围 (1-90) 中选择一个随机数,但排除某些数字。排除的数字是动态创建的,但假设它们是 3、8 和 80。
I have managed to create random number generator but couldn't identify any functions that let me fulfill my requirements.
我设法创建了随机数生成器,但无法确定任何可以满足我要求的函数。
Random r = new Random();
this.num = r.Next(1, 90);
The numbers which are to be excluded are previously generated numbers. So, if the random number is one, this would then get added to the excluded numbers list.
要排除的数字是先前生成的数字。因此,如果随机数为 1,则它将被添加到排除的数字列表中。
采纳答案by David
Using some handy extension methods here, you can create a range of numbers and select randomly from that rage. For example, with these extension methods:
在这里使用一些方便的扩展方法,您可以创建一系列数字并从该范围中随机选择。例如,使用这些扩展方法:
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);
}
You can apply these to a filtered range of numbers:
您可以将这些应用于过滤后的数字范围:
var random = Enumerable.Range(1, 90).Except(arrayOfRemovedNumbers).RandomElement();
回答by gleng
Create a container which holds the numbers you do not want:
创建一个包含您不想要的数字的容器:
var excludedNumbers = new List<int> { 1, 15, 35, 89 };
Then use do something like:
然后使用执行以下操作:
Random random = new Random();
int number;
do
{
number = r.Next(1, 90);
} while (excludedNumbers.Contains(number));
// number is not in the excluded list now
回答by gleng
Might not be the best choice but you can use a while loop to check the numbers you don't want
可能不是最好的选择,但您可以使用 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);
For much numbers you can use an array or a list and loop through them
对于很多数字,您可以使用数组或列表并遍历它们
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));
回答by mbeckish
Your latest update, which implies that each value can only be selected once, makes the problem easy.
您的最新更新(这意味着每个值只能选择一次)使问题变得简单。
- Create a collection of values within the range.
- Randomly shuffle the collection.
- To"randomly" select an item, just return the first item in the collection, and remove it from the collection.
- 创建范围内的值集合。
- 随机洗牌集合。
- 要“随机”选择一个项目,只需返回集合中的第一个项目,并将其从集合中删除。
回答by Andreas Adler
Make sure excludedNumbersis a HashSetfor best performance.
确保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();
回答by puretppc
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
}
}
回答by Bas
This solution does it in O(n) worst case where n is your list of exclusions, and constant memory. The code is a little longer but might be relevant if you:
此解决方案在 O(n) 最坏情况下执行此操作,其中 n 是您的排除列表和常量内存。代码有点长,但如果您:
- Possibly have a huge list of exclusions
- Need to run this many times
- Have a large range
- 可能有大量的排除项
- 需要多次运行这个
- 范围大
It preserves the random distribution in the sense that it actually skips the exclusion list and generates a random number within the range excluding the set.
它保留了随机分布,因为它实际上跳过了排除列表并在排除集合的范围内生成了一个随机数。
This is the implementation:
这是实现:
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;
}
And a test function to make sure it works (over 100k elements)
以及确保其正常工作的测试功能(超过 10 万个元素)
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");
}

