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);
我正在编写一个程序,它获取用户数据值 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);