在 C# 中分组并计数 w/ Console.WriteLine
Group by and count in C# w/ Console.WriteLine
我正在尝试 console.writeline 我的答案,但我遗漏了一些东西,经过 2 小时的搜索,我无法弄清楚。
我想让我的控制台说
Apple Large 2
Apple Mid 1
Apple Small 2
它的目标是说出类型、尺寸、将尺寸组合在一起,并说明每个尺寸有多少种尺寸
这是我的代码,任何帮助将不胜感激谢谢
namespace AppleGrouping
{
class Program
{
static void Main(string[] args)
{
var buckets = new List<Ap>()
{
new Ap { Type = "Apple", Size = "Large" },
new Ap { Type = "Apple", Size = "Small" },
new Ap { Type = "Apple", Size = "Mid" },
new Ap { Type = "Apple", Size = "Large" },
new Ap { Type = "Apple", Size = "Small" },
};
var numberGroups = buckets.GroupBy(ap => ap.Size);
foreach (var grp in numberGroups)
{
var number = grp.Key;
var total = grp.Count();
}
foreach (var ap in grp)
Console.WriteLine(ap.Type + " " + grp.Key);
}
public class Ap
{
public string Type { get; set; }
public string Size { get; set; }
}
}
}
您的问题在这里:
// This stores the data in groups, with the Size as key...
var numberGroups = buckets.GroupBy(ap => ap.Size);
// here, you're storing key and count in temporary variables,
// but not doing anything with them.
foreach (var grp in numberGroups)
{
var number = grp.Key;
var total = grp.Count();
}
将最后一位替换为:
foreach (var grp in numberGroups)
{
Console.WriteLine("Apple " + grp.Key + " " + grp.Count());
}
最后一个foreach
循环是错误的,甚至不需要,
下面将打印出您预期的结果,
foreach (var grp in numberGroups)
{
var size = grp.Key; //I renamed number variable to size
var total = grp.Count();
Console.WriteLine($"{grp.First().Type} {size} {total}");
}
为什么最后一个循环是错误的?
- 在最后一个 foreach 循环中,您试图遍历
grp
不在 class 范围内的变量。您将 grp
定义为第一个 foreach
循环的迭代器。因此 grp
变量的范围仅限于该循环。
为什么不需要最后一个循环?
- 在您的第一个 foreach 循环中,您拥有要在控制台上打印的所有值,您只需要在同一个循环中编写
Console.WriteLine()
,而不是编写单独的 foreach
循环仅用于打印详细信息。
旁注,也许有一天您的列表将包含的不仅仅是苹果,因此您也可以按类型分组并打印出来:
var numberGroups = buckets.GroupBy(ap => new { ap.Size, ap.Type } );
foreach (var grp in numberGroups)
{
var typeAndSize = grp.Key;
var total = grp.Count();
Console.WriteLine($"Type: {typeAndSize.Type}, Size: {typeAndSize.Size}, Count: {total}");
}
new { ap.Size, ap.Type }
是 c# 中非常有用的工具;它被称为匿名类型,它就像编译器为我们编写的迷你 class,因此我们不必编写专用的。它做了一些典型的 classes 不做的额外事情,这使得它在分组情况下非常有用;当 GroupBy 评估一个 class 实例是否等于另一个实例时,它将使用 Equals 方法。默认情况下,它来自 Object,即 C# 中所有内容的父级 class。对象的 Equals 方法 returns 如果被比较的两个事物在 C# 中存在于相同的内存地址,则为真。这很有用,但是如果您有两个具有相同数据值但位于不同内存地址的不同对象(就像您对两个大苹果所做的那样),它会说它们不相等。这意味着如果您只是要求 GroupBy 按原样直接对对象进行分组,它不会对任何内容进行分组,因为它们都被认为彼此不相等。如果匿名类型的所有数据都相同,则匿名类型被认为是相等的,因此因为两个不同的实例都是“Large”和“Apple”,GroupBy 会将它们视为相同
(您也可以提供自己的 Equals 和 GetHashCode 版本来检查两个不同的 Ap 并比较它们的数据,以获得相同的结果,但对于此用例,使用匿名类型更容易)
我正在尝试 console.writeline 我的答案,但我遗漏了一些东西,经过 2 小时的搜索,我无法弄清楚。
我想让我的控制台说
Apple Large 2
Apple Mid 1
Apple Small 2
它的目标是说出类型、尺寸、将尺寸组合在一起,并说明每个尺寸有多少种尺寸 这是我的代码,任何帮助将不胜感激谢谢
namespace AppleGrouping
{
class Program
{
static void Main(string[] args)
{
var buckets = new List<Ap>()
{
new Ap { Type = "Apple", Size = "Large" },
new Ap { Type = "Apple", Size = "Small" },
new Ap { Type = "Apple", Size = "Mid" },
new Ap { Type = "Apple", Size = "Large" },
new Ap { Type = "Apple", Size = "Small" },
};
var numberGroups = buckets.GroupBy(ap => ap.Size);
foreach (var grp in numberGroups)
{
var number = grp.Key;
var total = grp.Count();
}
foreach (var ap in grp)
Console.WriteLine(ap.Type + " " + grp.Key);
}
public class Ap
{
public string Type { get; set; }
public string Size { get; set; }
}
}
}
您的问题在这里:
// This stores the data in groups, with the Size as key...
var numberGroups = buckets.GroupBy(ap => ap.Size);
// here, you're storing key and count in temporary variables,
// but not doing anything with them.
foreach (var grp in numberGroups)
{
var number = grp.Key;
var total = grp.Count();
}
将最后一位替换为:
foreach (var grp in numberGroups)
{
Console.WriteLine("Apple " + grp.Key + " " + grp.Count());
}
最后一个foreach
循环是错误的,甚至不需要,
下面将打印出您预期的结果,
foreach (var grp in numberGroups)
{
var size = grp.Key; //I renamed number variable to size
var total = grp.Count();
Console.WriteLine($"{grp.First().Type} {size} {total}");
}
为什么最后一个循环是错误的?
- 在最后一个 foreach 循环中,您试图遍历
grp
不在 class 范围内的变量。您将grp
定义为第一个foreach
循环的迭代器。因此grp
变量的范围仅限于该循环。
为什么不需要最后一个循环?
- 在您的第一个 foreach 循环中,您拥有要在控制台上打印的所有值,您只需要在同一个循环中编写
Console.WriteLine()
,而不是编写单独的foreach
循环仅用于打印详细信息。
旁注,也许有一天您的列表将包含的不仅仅是苹果,因此您也可以按类型分组并打印出来:
var numberGroups = buckets.GroupBy(ap => new { ap.Size, ap.Type } );
foreach (var grp in numberGroups)
{
var typeAndSize = grp.Key;
var total = grp.Count();
Console.WriteLine($"Type: {typeAndSize.Type}, Size: {typeAndSize.Size}, Count: {total}");
}
new { ap.Size, ap.Type }
是 c# 中非常有用的工具;它被称为匿名类型,它就像编译器为我们编写的迷你 class,因此我们不必编写专用的。它做了一些典型的 classes 不做的额外事情,这使得它在分组情况下非常有用;当 GroupBy 评估一个 class 实例是否等于另一个实例时,它将使用 Equals 方法。默认情况下,它来自 Object,即 C# 中所有内容的父级 class。对象的 Equals 方法 returns 如果被比较的两个事物在 C# 中存在于相同的内存地址,则为真。这很有用,但是如果您有两个具有相同数据值但位于不同内存地址的不同对象(就像您对两个大苹果所做的那样),它会说它们不相等。这意味着如果您只是要求 GroupBy 按原样直接对对象进行分组,它不会对任何内容进行分组,因为它们都被认为彼此不相等。如果匿名类型的所有数据都相同,则匿名类型被认为是相等的,因此因为两个不同的实例都是“Large”和“Apple”,GroupBy 会将它们视为相同
(您也可以提供自己的 Equals 和 GetHashCode 版本来检查两个不同的 Ap 并比较它们的数据,以获得相同的结果,但对于此用例,使用匿名类型更容易)