下文参考翻译自:
故事的背景
让我们先来创建一个简单的类来表示产品,产品有ID,类别,和价格,这个类没有什么特别:
public sealed class Product
{
public int Id { get ; set ; }
public string Category { get ; set ; }
public double Value { get ; set ; }
public override string ToString()
{
return string .Format("[{0}: {1} - {2}] ", Id, Category, Value);
}
}
然后我们加入一个函数得到一个产品的列表,当然你也可以从数据库中读取出来:
public static List<Product> GetList()
{
var products = new List<Product>
{
new Product {Id = 1, Category = "Electronics ", Value = 15.0},
new Product {Id = 2, Category = "Groceries ", Value = 40.0},
new Product {Id = 3, Category = "Garden ", Value = 210.3},
new Product {Id = 4, Category = "Pets ", Value = 2.1},
new Product {Id = 5, Category = "Electronics ", Value = 19.95},
new Product {Id = 6, Category = "Pets ", Value = 21.25},
new Product {Id = 7, Category = "Pets ", Value = 5.50},
new Product {Id = 8, Category = "Garden ", Value = 13.0},
new Product {Id = 9, Category = "Automotive ", Value = 10.0},
new Product {Id = 10, Category = "Electronics ", Value = 250.0},
};
return products;
}
我们有一个任务就是按类别列出一个物品清单,这个非常的容易,用GroupBy 就可以实现了:
foreach (var group in products.GroupBy(p => p.Category))
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine("\t " + item);
}
}
看起来一切都很好,没有什么问题.
当我们使用 GroupBy() 扩展方法时,使用了延迟执行。 这意味着,当你遍历集合的时候,下一个要出现的项目可能会或者可能不会被加载。 这是一个很大的性能改进,但它会引起有趣的副作用。
在用 GroupBy() 时, 它实际上是在第一项被使用的时候创建分组,而不是在 GroupBy() 第一次被调用时。
考虑一下:如果你从数据库中加载数据,然后想组合到一起,并存储快速查找。 看下面的一段代码:
var groups = products.GroupBy(p => p.Category);
//删除所有属于Garden的产品
products.RemoveAll(p => p.Category == "Garden ");
foreach (var group in groups)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine("\t " + item);
}
}
执行后发现,所有的Garden产品都已经消失了,但是 groups 是在执行删除命令前就已经赋值了。
基于这种情况,我们不得不使用ToDictionary() 将GroupBy 后的结果储存起来,这样一来工作量就增加了,而且维护也不太方便 -- 请大家试试。
ToLookup登场
现在我们有请ToLookup。
该 ToLookup() 方法创建一个类似 字典(Dictionary ) 的列表List, 但是它是一个新的 .NET Collection 叫做 lookup。 Lookup,不像Dictionary, 是不可改变的。 这意味着一旦你创建一个lookup, 你不能添加或删除元素。
var productsByCategory = products.ToLookup(p => p.Category);
foreach (var group in productsByCategory)
{
// the key of the lookup is in key property
Console.WriteLine(group.Key);
// the list of values is the group itself.
foreach (var item in group)
{
Console.WriteLine("\t " + item);
}
}
你还可以使用类似索引的功能得到某个项目,在本案例中是得到某个类别的所有产品:
private static void PrintCategory(ILookup<string , Product> productsByCategory,string categoryName)
{
foreach (var item in productsByCategory[categoryName])
{
Console.WriteLine(item);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架