快速搜索
主页 > 软件开发 > C#开发 >

走进C#奇妙函数之ToLookup

时间:2011-04-12 23:18来源:未知 作者:admin 点击:
分享到:
这个系列,我和大家一起来学学C#中一些非常有用函数,对于有些人来说可能它们不起眼,因此常常忽略它们。它们不会嚷嚷到:使用我吧!我会让你节省很多的时间,而且让你的代码

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

好的!先来看看ToLookup:

故事的背景

让我们先来创建一个简单的类来表示产品,产品有ID,类别,和价格,这个类没有什么特别:

  1. public?sealed?class?Product ?
  2. ?
  3. ???public?int?Id?{?get;?set;?} ?
  4. ???public?string?Category?{?get;?set;?} ?
  5. ???public?double?Value?{?get;?set;?} ?
  6. ?? ?
  7. ?
  8. ???public?override?string?ToString() ?
  9. ???{ ?
  10. ???????return?string.Format("[{0}:?{1}?-?{2}]",?Id,?Category,?Value); ?
  11. ???} ?

然后我们加入一个函数得到一个产品的列表,当然你也可以从数据库中读取出来:

  1. public?static?List?GetList() ?
  2. ?{ ?
  3. ?????var?products?=?new?List ?
  4. ????????????????????????{ ?
  5. ????????????????????????????new?Product?{Id?=?1,?Category?=?"Electronics",?Value?=?15.0}, ?
  6. ????????????????????????????new?Product?{Id?=?2,?Category?=?"Groceries",?Value?=?40.0}, ?
  7. ????????????????????????????new?Product?{Id?=?3,?Category?=?"Garden",?Value?=?210.3}, ?
  8. ????????????????????????????new?Product?{Id?=?4,?Category?=?"Pets",?Value?=?2.1}, ?
  9. ????????????????????????????new?Product?{Id?=?5,?Category?=?"Electronics",?Value?=?19.95}, ?
  10. ????????????????????????????new?Product?{Id?=?6,?Category?=?"Pets",?Value?=?21.25}, ?
  11. ????????????????????????????new?Product?{Id?=?7,?Category?=?"Pets",?Value?=?5.50}, ?
  12. ????????????????????????????new?Product?{Id?=?8,?Category?=?"Garden",?Value?=?13.0}, ?
  13. ????????????????????????????new?Product?{Id?=?9,?Category?=?"Automotive",?Value?=?10.0}, ?
  14. ????????????????????????????new?Product?{Id?=?10,?Category?=?"Electronics",?Value?=?250.0}, ?
  15. ????????????????????????}; ?
  16. ?????return?products; ?
  17. ?}?

我们有一个任务就是按类别列出一个物品清单,这个非常的容易,用GroupBy 就可以实现了:

  1. foreach?(var?group?in?products.GroupBy(p?=>?p.Category)) ?
  2. ?
  3. ???Console.WriteLine(group.Key); ?
  4. ???foreach?(var?item?in?group) ?
  5. ???{ ?
  6. ???????Console.WriteLine("\t"?+?item); ?
  7. ???} ?


看起来一切都很好,没有什么问题.

当我们使用 GroupBy() 扩展方法时,使用了延迟执行。 这意味着,当你遍历集合的时候,下一个要出现的项目可能会或者可能不会被加载。 这是一个很大的性能改进,但它会引起有趣的副作用。

在用 GroupBy()时,? 它实际上是在第一项被使用的时候创建分组,而不是在 GroupBy() 第一次被调用时。

考虑一下:如果你从数据库中加载数据,然后想组合到一起,并存储快速查找。? 看下面的一段代码:

  1. ?var?groups?=?products.GroupBy(p?=>?p.Category); ?
  2. //删除所有属于Garden的产品 ?
  3. products.RemoveAll(p?=>?p.Category?==?"Garden"); ?
  4. ?
  5. foreach?(var?group?in?groups) ?
  6. { ?
  7. ????Console.WriteLine(group.Key); ?
  8. ????foreach?(var?item?in?group) ?
  9. ????{ ?
  10. ????????Console.WriteLine("\t"?+?item); ?
  11. ????} ?
  12. }?

执行后发现,所有的Garden产品都已经消失了,但是 groups 是在执行删除命令前就已经赋值了。

基于这种情况,我们不得不使用ToDictionary() 将GroupBy 后的结果储存起来,这样一来工作量就增加了,而且维护也不太方便 -- 请大家试试。

ToLookup登场

现在我们有请ToLookup。

该 ToLookup() 方法创建一个类似 字典(Dictionary ) 的列表List, 但是它是一个新的 .NET Collection 叫做 lookup。 Lookup,不像Dictionary, 是不可改变的。 这意味着一旦你创建一个lookup, 你不能添加或删除元素。

  1. ?var?productsByCategory?=?products.ToLookup(p?=>?p.Category); ?
  2. ?
  3. ?foreach?(var?group?in?productsByCategory) ?
  4. { ?
  5. ????//?the?key?of?the?lookup?is?in?key?property ?
  6. ????Console.WriteLine(group.Key); ?
  7. ????//?the?list?of?values?is?the?group?itself. ?
  8. ????foreach?(var?item?in?group) ?
  9. ????{ ?
  10. ????????Console.WriteLine("\t"?+?item); ?
  11. ????} ?
  12. }?

你还可以使用类似索引的功能得到某个项目,在本案例中是得到某个类别的所有产品:

  1. ?private?static?void?PrintCategory(ILookup<string,?Product>?productsByCategory,string?categoryName) ?
  2. { ?
  3. ????foreach?(var?item?in?productsByCategory[categoryName]) ?
  4. ????{ ?
  5. ????????Console.WriteLine(item); ?
  6. ????} ?
  7. }?


结论

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

:http://www.cnblogs.com/multiplesoftware/archive/2011/03/31/2000528.html
精彩图集

赞助商链接