C# 为循环中的每个数字添加计数器

C# Add counter for each number in loop

我正在编写一个程序,它获取用户数据值 1-10 并将其存储到一个数组中。我想弄清楚如何添加一个计数器,让我可以输出每个数字被输入了多少次以及输入了多少无效数字。

    class Program
{
    static void Main(string[] args)
    {
        int[] data = GetData();
    }

    private static int[] GetData()
    {
        int[] dataArray = new int[100];
        int n = 0;
        int intValue = 0;

        while (true)
        {
            Console.WriteLine("Enter a number 0-10 (Q to end)");
            string lineValue = Console.ReadLine();

            if (lineValue.ToLower().Trim().Equals("q"))
            {
                break;
            }

            if (!int.TryParse(lineValue, out intValue))
            {
                Console.WriteLine("INVALID DATA - Try again.");
                continue;
            }

            if (intValue < 0 || intValue > 10)
            {
                Console.WriteLine("NUMERIC DATA OUT OF RANGE - Try again.");
                continue;
            }

            dataArray[++n] = intValue;
            dataArray[0] = n;
        }
        return dataArray;
    }
}

您已经有了一个计数器 (n) 的示例,您可以将其用作记录无效输入次数的示例。只需在这个 if 块中递增它:

if (intValue < 0 || intValue > 10)
        {
            Console.WriteLine("NUMERIC DATA OUT OF RANGE - Try again.");
            myInvalidCounter ++;
            continue;
        }

要计算输入的每个数字 - 您可以分析存储在 dataArray 中的数据。

编辑:我刚刚注意到您有两个无效数据示例 - 错误的原始数据和超出范围的数据 - 您需要适当地设置计数器 - 也许每个一个或共享一个等。

您可以在 while 条件之前为无效数字设置一个计数器。

int invalidNumbersCounter = 0;

然后您可以在每次输入无效时递增此计数器:

if (!int.TryParse(lineValue, out intValue))
{
    Console.WriteLine("INVALID DATA - Try again.");
    invalidNumbersCounter++;  
    continue;
}

关于你的另一个问题,每个数字有多少次,你可以使用普通的 LINQ 来解决这个问题。

static void Main(string[] args)
{
    int[] data = GetData();

    var statistics = data.GroupBy(x=>x)
                         .Select(gr => new 
                         { 
                             Number = gr.key, 
                             Times = gr.Count() 
                         });

    foreach(var statistic in statistics)
    {
        Console.WriteLine(String.Format("The number {0} found {1} times in you array", statistic.Number, statistic.Times));
    }
}

上述查询的结果将是具有两个属性的匿名类型的对象序列,即数字和该数字在数组中的数字。

更新

为了避免计算用户未输入的值,本质上是数组的初始值,我们可以在创建数组时将数组的值初始化为-1,比如下面:

int[] dataArray = Enumerable.Repeat(-1, 100).ToArray();

然后我们必须将 linq 查询更新为以下查询:

 var statistics = data.Skip(1)
                      .Where(number => number!=-1)
                      .GroupBy(x=>x)
                      .Select(gr => new 
                      { 
                          Number = gr.key, 
                          Times = gr.Count() 
                      });

你可以这样做:

public class Program
{
    public static void Main(string[] args)
    {
        // note updated to use a list rather than array (just preference)
        List<int> data = GetData();         
    }

    private static List<int> GetData()
    {
        List<int> list = new List<int>();
        int intValue = 0;
        int invalidAttempts = 0; // added to keep track of invalid values

        while (true)
        {
            Console.WriteLine("Enter a number 0-10 (Q to end)");
            string lineValue = Console.ReadLine();

            if (lineValue.ToLower().Trim().Equals("q"))
            {
                break;
            }

            if (!int.TryParse(lineValue, out intValue))
            {
                Console.WriteLine("INVALID DATA - Try again.");
                invalidAttempts++;
                continue;
            }

            if (intValue < 0 || intValue > 10)
            {
                Console.WriteLine("NUMERIC DATA OUT OF RANGE - Try again.");
                invalidAttempts++;
                continue;
            }

            list.Add(intValue);
        }

        Console.WriteLine("Invalid attempts {0}", invalidAttempts);

        // this is using linq to group by the individual numbers (keys),
        // then creates an anon object for each key value and the number of times it occurs.
        // Create new anon object numbersAndCounts
        var numbersAndCounts = list
            // groups by the individual numbers in the list
            .GroupBy(gb => gb)
            // selects into a new anon object consisting of a "Number" and "Count" property
            .Select(s => new {
                Number = s.Key,
                Count = s.Count()
            });

        foreach (var item in numbersAndCounts)
        {
            Console.WriteLine("{0} occurred {1} times", item.Number, item.Count);
        }

        return list;
    }
}

请注意,我使用的是 list 而不是 array,我发现它们更易于使用。

工作演示:

https://dotnetfiddle.net/KFz1UY

Is it possible to make the output go in numeric order? Right now it just displays whatever numbers were typed first. Such as 1, 7, 7, 4 would be 1:1 7:2 4:1, how can I change this to go 1:1 4:1 7:2?

当然可以!见下文(和更新的原始演示)

我刚刚更改:

    var numbersAndCounts = list
        .GroupBy(gb => gb)
        .Select(s => new {
            Number = s.Key,
            Count = s.Count()
        });

至:

    var numbersAndCounts = list
        .GroupBy(gb => gb)
        .Select(s => new {
            Number = s.Key,
            Count = s.Count()
        })
        .OrderBy(ob => ob.Number);