我正在构建一个c#windows应用程序表单。 到目前为止,我已经生成了一个随机数算法,该算法用30(int)随机数填充列表框。 我没有使用数组,因为列表框本身就是一个数组。
我的问题是当我点击按钮生成30个随机数字时。这些数字已填充,但我有可能产生重复的数字,我希望防止这种情况发生。
我希望能够使用HashSet或Distinct方法来防止重复。我使用了一个简单的.Distinct来删除重复项,但它不会阻止重复项填充到列表中。
注意:我无法对列表框进行排序,因为我有单独的功能。
private void GenerateNumbers_Click(object sender, EventArgs e)
{
List<int> nums = new List<int>();
Random rnd = new Random();
//HashSet<int> duplicate = new HashSet<int>();
//IEnumerable<int> RemoveDuplicates = numberList.Distinct();
int produce;
for (int i = 0; i < 30; i++)
{
produce = rnd.Next(1, 250);
this.nums.Items.Insert(0, produce.ToString());
}
GenerateNumbers.Enabled = false;
}
答案 0 :(得分:2)
所以你想要从1到250的30个数字?创建一个包含所有数字shuffle it的数组,然后取前30个。例如:
Random rand = new Random();
// create an array with 250 numbers, in order
var numbers = Enumerable.Range(1, 250).Select(x => x).ToArray();
// shuffle
for (int i = numbers.Length - 1; i > 0; --i)
{
int n = rand.Next(i+1);
int t = numbers[i];
numbers[i] = numbers[n];
numbers[n] = t;
}
// from here, just take the first 30 numbers
答案 1 :(得分:1)
我会选择一个枚举器:
// will produce as many ints as needed (with duplicates).
// do not call: YieldRandomInt(1,250).ToList();
static IEnumerable<int> YieldRandomInt(int min, int max)
{
Random r = new Random();
while (true)
yield return r.Next(min, max);
}
// Gets as many distinct ints as needed and produces a list for you
static IList<int> GetDistinctRandomInts(int count, int min, int max)
{
return YieldRandomInt(min, max).Distinct().Take(count).ToList();
}
你的算法只需拨打var rnds = GetDistinctRandomInts(30,1,250);
洗牌方法也很好,为穷人(或富人?)洗牌:
Enumerable.Range(1, 250).OrderBy(r => Guid.NewGuid()).Take(30).ToList();
这将在每次调用时创建250个Guid并重新排序创建的范围 - 需要一些努力。它的随机性不是计算上/密码学上的声音 - 但是Random也不是。 (仍然:如果你多次打电话,请随机使用)
答案 2 :(得分:1)
稍微改变你的算法:
private void GenerateNumbers_Click(object sender, EventArgs e)
{
List<int> nums = new List<int>(30);
Random rnd = new Random();
while (true)
{
int num = rnd.Next(1, 250);
if (!nums.Contains(num))
{
nums.Add(num);
}
if (nums.Count == 30)
{
break;
}
}
// elided
}
提案编辑:
private void GenerateNumbers_Click(object sender, EventArgs e)
{
var nums = new HashSet<int>();
Random rnd = new Random();
while (nums.Count < 30)
nums.Add(rnd.Next(1, 250));
// use nums.ToList();
}