【问题标题】:Array, prevent user to write same value数组,防止用户写入相同的值
【发布时间】:2020-10-04 11:54:38
【问题描述】:

我正在使用数组来保存我的数字,但是我不希望 userInput 等于数组中的相同值。 int[] userNum = new int[100];
如果 userInput 是 1,并且 1 已经存储在数组中,我希望代码告诉用户 “输入错误”我尝试使用 userNum[i] != userNum[i],没有用。 我目前不使用列表,但我计划很快去那里。现在我正在尝试更好地理解数组,以及如何使用它们。我很高兴能在这方面得到所有帮助。

            for (int i = 0; i < userNum.Length; i++)
            { 
            try
            {
                array[i] = int.Parse(Console.ReadLine());
                Console.WriteLine("Number {0}", (i + 1));
            }
            catch (SystemException)
            {
                i--;
                Console.WriteLine("Invalid input try again");

                continue;
            }
            if (userNum[i] < min || userNum[i] >
                max || userNum[i] != userNum[i])  // this does not work
            {
                i--;
                Console.WriteLine("Invalid number, try again");
                continue;
            }
            }

最好的问候

【问题讨论】:

    标签: c# arrays list duplicates


    【解决方案1】:

    您必须遍历每个存储的元素,并检查新元素是否与它们匹配。如果是,则表示它已被存储,因此该数字无效。否则,你存储它。

    if (userNum[i] < min || userNum[i] > max) {
                    i--;
                    Console.WriteLine("Invalid number, try again");
                    continue;
    }
    for(int j = 0; j < i; j++)
    {
        if(userNum[i] == userNum[j]) {
                    i--;
                    Console.WriteLine("Invalid number, try again");
                    break;
        //TODO something to "continue;" if needed
        }
    }
    

    【讨论】:

    • Zenkii1337 感谢您抽出宝贵时间!我从没想过这种方法,出于某种原因,我认为我的代码循环并检查了存储的值。我感谢你的帮助。谢谢。
    【解决方案2】:

    您最好使用具有“包含”方法的列表来查看是否已经在列表中。

    public void EnterNumbers()
    {
        var myInts = new List<int>();
        int tryConvert;
        while( myInts.Count < 100)
        {
            Console.WriteLine("Enter a number not already in list: ");
            var userEntry = Console.ReadLine();
            if (int.TryParse(userEntry, out tryConvert))
            {
                // if WAS able to convert to a number, now check if in the list
                if (myInts.Contains(tryConvert))
                    Console.WriteLine("Number already in list");
                else
                    myInts.Add(tryConvert);
            }
            else
            {
                // allow user to enter a "Q" to quit vs adding all 100 entries
                if (userEntry == "Q")
                    break;
    
                Console.WriteLine("Not a valid number");
            }
        }
    }
    

    【讨论】:

    • 感谢 DRapp,感谢您抽出宝贵时间。正如您所说,我已经看到了类似的“解决问题”方法,我觉得这非常好,但是我仍然不确定数组是否更好或列表。我知道它们是相似的,但是我将深入研究并尝试更好地理解它们。再次感谢。
    • @UndeadSpace,列表很好,因为您仍然可以使用索引位置 [0]、[1] 等循环遍历它们...并根据 myInts.Count 与固定的已知数字循环。也可用于绑定,例如数据网格等,您也可以拥有其他事物的列表(来自数据库查询的记录)。但是找到适合你的。
    • 我还是个编码初学者,还不知道如何最好地利用代码。我希望将来我能帮助像你这样的人。再次感谢。将研究数据网格以及如何以更好的方式使用列表。
    【解决方案3】:

    您可以使用Contains 方法检查您的数组userNum 是否包含新输入:

    if (userNum.Contains(array[i]))
    {
        Console.WriteLine($"Invalid input, {array[i]} already present.");
    }
    

    我还建议使用稍微简单的方法和不同的数据结构 (HashSet) 来实现相同的结果,但代码更少。另一个小建议 - 让用户知道为什么他们的输入号码无效。例如:

            public void ReadValues()
            {
                var min = -100;
                var max = 100;
                var successfulInputCount = 0;
                var userNum = new HashSet<int>();
                while (successfulInputCount < 100)
                {
                    try
                    {
                        var input = int.Parse(Console.ReadLine());
                        if (input < min || input > max)
                            Console.WriteLine($"Invalid input, number must be between {min} and {max}.");
    
                        var added = userNum.Add(input);
                        if (added)
                            successfulInputCount++;
                        else
                            Console.WriteLine($"Invalid input, {input} already present.");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"Invalid input, try again. Error message: {e.Message}");
                    }
                }
            }
    

    【讨论】:

    • 感谢 Tomaz 抽出宝贵时间!我一直在尝试使用 HashSet,但是我还没有信心使用它。据我了解,列表更适合更大的项目?我正在尝试更多地使用列表,但经常使用数组。我看到您经常使用 Var,您是否有理由不对数据类型进行硬编码?比如int、double。
    • 干杯伙伴,不客气。关于 HashSet 与 Array:对于较小的项目(或数组大小)而言,这并不是很重要,但很高兴知道当它确实产生影响时能够使用正确的数据结构。除了 Contains 方法的速度,它需要 O(1) 的 HashSet,但需要 O(N) 的数组,它还可以防止重复 - 如果你使用 HashSet,你的代码中不可能有错误将重复插入其中,而如果您使用数组,则需要确保它不会。
    • 至于var,它只是较新 C# 版本(已经很老了)的一个不错的现代功能。您不必重复变量的类型 - 例如,如果您定义整数数组或哈希集,为什么要在变量声明前重复类型。您只需键入var,您的编译器(大多数情况下是 IDE)就会显示正确的类型。此外,如果您需要更改您的变量,假设您需要有一个双精度数组,您只需在一个地方更改它,这样就不会那么大惊小怪了。您可以在其他页面上查看许多其他好处(如果有的话,缺点很少)。
    • 再次感谢 Tomaz 的澄清,我会坐下来阅读更多关于 HashSet 的内容,感觉它在未来的工作中会更胜一筹(因为我将从事更大的项目)。我还将开始更频繁地使用 var,因为我遇到了 exakt 问题,正如您所说的需要更改数据类型。再次感谢!最好的问候
    【解决方案4】:

    如果你想要更好的性能,你应该用 hashset 代替。 https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1?view=netcore-3.1#examples

    包含方法的时间复杂度为 1。 方法 Add 也很有帮助 如果元素被添加到 HashSet 对象,则返回 true;如果元素已经存在,则返回 false。

    如果您出于某种原因需要在输入的和处将哈希集转换为数组,您可以轻松使用

    使用 System.Linq;

    var mySet = new HashSet<int>();
    // load input data
    var myArray = mySet.ToArray();
    

    【讨论】:

    • 感谢您的链接!我一直在 youtube 和其他平台上学习更多关于 HashSet 的信息,据我所知,它更快,并且以后更容易塑造和弯曲代码。我将深入研究 HashSet。我感谢你的帮助!哦,从 HashSet 到数组的过渡很棒。我一定会用的。最好的问候
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    相关资源
    最近更新 更多