C# console app System.StackOverflowException' was thrown on big list/array

huangapple go评论67阅读模式
英文:

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.

C# console app System.StackOverflowException' was thrown on big list/array

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&lt;int&gt; list)
{
    while (list.Count &gt; 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&lt;int&gt; selectedNumbers = new HashSet&lt;int&gt;();

for (int i = 0; i &lt; 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:

https://dotnetfiddle.net/q6kAUp

huangapple
  • 本文由 发表于 2023年2月23日 21:40:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545612.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定