这个系列,我和大家一起来学学C#中一些非常有用函数,对于有些人来说可能它们不起眼,因此常常忽略它们。它们不会嚷嚷到:“使用我吧!我会让你节省很多的时间,而且让你的代码变得更加的简洁!” -- 但是,这些话会从对它们熟悉的程序员的脑海中涌现出来。

好的!先来看看ToLookup:

下文参考翻译自:

C#/.NET Little Wonders: The ToLookup() LINQ Extension Method

故事的背景

让我们先来创建一个简单的类来表示产品,产品有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 propertyConsole.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);}}

源代码下载

你从这里可以下载本案例的源码

结论

ToLookup() 是一个奇妙的函数,用于对一个集合进行操作,创建一个1:n 的映射。 它可以方便的将数据分类成组,并生成一个字典供查询使用。

转贴请注明:

喜乐的ASP.NET(Alex Song)

C# 中奇妙的函数 -- 1. ToLookup相关推荐

  1. 一起谈.NET技术,C# 中奇妙的函数之ToLookup

    我将和大家一起来学学C#中一些非常有用函数,对于有些人来说可能它们不起眼,因此常常忽略它们.它们不会嚷嚷到:使用我吧!我会让你节省很多的时间,而且让你的代码变得更加的简洁! -- 但是,这些话会从对它 ...

  2. C# 中奇妙的函数–6. 五个序列聚合运算(Sum, Average, Min, Max,Aggregate)

    今天,我们将着眼于五个用于序列的聚合运算.很多时候当我们在对序列进行操作时,我们想要做基于这些序列执行某种汇总然后,计算结果. Enumerable 静态类的LINQ扩展方法可以做到这一点 .就像之前 ...

  3. linux中的fork函数详解

    在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程.在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID.我们可以通过fork返回的值来 ...

  4. java sendmessage函数_vc中SendMessage自定义消息函数用法实例

    本文实例讲述了vc中SendMessage自定义消息函数用法,分享给大家供大家参考.具体如下: SendMessage的基本结构如下: SendMessage( HWND hWnd,  //消息传递的 ...

  5. c++中的fork函数_fork函数

    复刻(fork,又译作派生.分支)是UNIX或类UNIX中的分叉函数,fork函数将运行着的程序分为2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程.这两个进程中的线程继续 ...

  6. c++中的fork函数_fork( )函数详解

    一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程, 也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同 ...

  7. MySQL8中的开窗函数

    开窗函数 前言 窗口函数的格式 函数(Function)的类型 开窗函数over() 窗口函数使用 ROW_NUMBER() RANK()与DENSE_RANK() LEAD()与LAG() FIRS ...

  8. OpenCV 相机校正过程中,calibrateCamera函数projectPoints函数的重投影误差的分析

    OpenCV 校正过程中,calibrateCamera函数的ret和重投影误差的分析 OpenCV对相机进行校正的过程中,校正返回值retval和重投影误差的计算公式表示和分析. OpenCV 校正 ...

  9. Iar环境c语言调用汇编函数,如何在IAR EWARM中通过内联汇编程序在另一个模块中调用C函数?...

    我在硬故障处理程序中有一些程序集.程序集基本上是为了传递当前堆栈指针作为参数(在R0中).它看起来像这样...如何在IAR EWARM中通过内联汇编程序在另一个模块中调用C函数? __asm(&quo ...

最新文章

  1. Linux中输入输出重定向和管道
  2. 使用WildFly 8.2.0.Final,Primefaces 5.1和MySQL 5的JDBC领域和基于表单的身份验证
  3. document.all和document.layers
  4. mysql常用内置函数_mysql常见内置函数
  5. oracle 数据库日期定义,Oracle数据库实现日期遍历功能
  6. 测试人员做到这几点,线上80%的BUG将落入你手,企业将避免重大风险
  7. 获取文件的后缀名 和 Process进程
  8. java中的mod运算_Java源码中Integer类位运算分析
  9. matlab怎么相加相同id的几行,matlab几个有用的技巧
  10. 使用iMazing为iPad添加PDF文档
  11. docker下nginx反向代理和负载均衡配置
  12. synchronized的实现原理用法详解
  13. Docker CE 安装教程
  14. 如何将python转换成exe执行
  15. iPad 上播放 2160p (4K) mkv 视频的方法
  16. 怎样用手机照出证件照
  17. yocs_velocity_smoother速度平滑配置与使用
  18. HDU-ACM程序设计——BFS(宽度优先搜索)
  19. C:exit(0),_exit(0),exit(1),exit(-1)作用与区别
  20. LOJ P2448 :无尽的生命 树状数组 + 离散化

热门文章

  1. 第二次作业——个人项目实战
  2. Centos基础优化
  3. Linux socket 网络编程常用函数总结
  4. struts2+jquery之form插件实现异步上传图片并显示
  5. winxp登陆后自动注销
  6. .NET,你忘记了么?(二)——使用using清理非托管资源
  7. Raspberry 4B安装wiringPi库 和 python-dev包
  8. OpenCV 图像旋转
  9. 浏览器输入 URL 之后的链路
  10. cinder块存储配置使用lvm