英文:
C# console app System.StackOverflowException' was thrown on big list/array
问题
我在尝试为一个朋友编写一个简单的控制台应用程序,他想要用它来进行抽奖。该应用在小列表上运行良好,但随着列表的增长,它变得越来越慢,最终引发了溢出异常。当列表长度小于5,000时,它能正常工作。
该应用程序要求输入起始票号、结束票号和中奖号码。然后,它从列表中取随机号码并删除它们,以确保没有重复出现。
据我了解,问题不在于列表的长度,而是在于从列表中选择号码并立即删除的方法。
你可以在这里看到代码:
dotnetfiddle script
英文:
I trying to write a simple console app for a friend that want to use it for lottery. The app is working fine on small list but as the list grows, it became slower and finally it throws overflow exception. When the list length is less than 5.000, it works fine.
The app asks for starting ticket number, ending ticket number and winning numbers. Then it takes rnadom numbers of the list and delete them so no dublicates occur.
As i understand, the problem is not the length of the list, but the method that select the number from the list and removes right after.
You can see the code here:
dotnetfiddle script
The console app is compiled with .net 4.8
答案1
得分: 2
Use a loop instead of recursion, and only call .ToList()
once for the array
使用循环而不是递归,并只调用一次 .ToList()
来处理数组
public static int GetNumber(int[] arr)
{
return GetNumber(arr.ToList());
}
public static int GetNumber(List<int> list)
{
while (list.Count > 1)
{
//Remove random number from list
list.RemoveAt(random.Next(0, list.Count));
}
return list[0];
}
Though, if I understood what you are trying to accoplish you could just do this instead
尽管,如果我理解你要达到的目标,你可以尝试这样做:
// 创建一个 HashSet,因为这种类型只能包含唯一的条目
HashSet<int> selectedNumbers = new HashSet<int>();
for (int i = 0; i < numberOfWinningTickets; i++)
{
while(true)
{
// + 1 是因为 upperBound 是排除的
var r = random.Next(startingNumber, endingNumber + 1);
var added = selectedNumbers.Add(r);
// 如果成功添加了一个唯一的数字到 SelectedNumbers,added 将为 TRUE
if (added == true)
break;
}
}
查看示例:
查看示例:
https://dotnetfiddle.net/q6kAUp
英文:
Use a loop instead of recursion, and only call .ToList()
once for the array
public static int GetNumber(int[] arr)
{
return GetNumber(arr.ToList());
}
public static int GetNumber(List<int> list)
{
while (list.Count > 1)
{
//Remove random number from list
list.RemoveAt(random.Next(0, list.Count));
}
return list[0];
}
Though, if I understood what you are trying to accoplish you could just do this instead
//create a hashSet as this type can only contain unique entries
HashSet<int> selectedNumbers = new HashSet<int>();
for (int i = 0; i < numberOfWinningTickets; i++)
{
while(true)
{
//+ 1 because the upperBound is exclusive
var r = random.Next(startingNumber, endingNumber + 1);
var added = selectedNumbers.Add(r);
//added will be TRUE if a unique number got added to SelectedNumbers
if (added == true)
break;
}
}
See an example:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论