2009-09-10 24 views

回答

172

这是一个IGrouping和字典之间的交叉。它可以让你通过一个键将项目分组在一起,但是通过这个键以高效的方式访问它们(而不是仅仅遍历它们,这是GroupBy可以让你做的)。

例如,你可以采取.NET类型的负载,并建立由命名空间查找......然后得到在特定的命名空间的所有类型很容易:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Xml; 

public class Test 
{ 
    static void Main() 
    { 
     // Just types covering some different assemblies 
     Type[] sampleTypes = new[] { typeof(List<>), typeof(string), 
            typeof(Enumerable), typeof(XmlReader) }; 

     // All the types in those assemblies 
     IEnumerable<Type> allTypes = sampleTypes.Select(t => t.Assembly) 
               .SelectMany(a => a.GetTypes()); 

     // Grouped by namespace, but indexable 
     ILookup<string, Type> lookup = allTypes.ToLookup(t => t.Namespace); 

     foreach (Type type in lookup["System"]) 
     { 
      Console.WriteLine("{0}: {1}", 
           type.FullName, type.Assembly.GetName().Name); 
     } 
    } 
} 

(我通常。使用var大多数这些声明的,在正常的代码)

+43

我觉得做这个答案更好,你可以代替某些瓦尔的。为了学习的目的,我认为当类型明确表达时,更容易遵循。只是我的2美分:) – 2009-09-16 03:42:02

+3

如果它具有两个世界的最佳,那么为什么要打扰字典? – 2013-03-21 02:30:20

+12

@KyleBaran:因为对于真正的键/值对集合,每个键只有一个值是没有意义的。 – 2013-03-21 06:41:45

11

我还没有成功地使用过它,但这里是我去:

一个Lookup<TKey, TElement>会表现得非常像(关系型)数据库的索引一个没有独特的表格e约束。在相同的地方使用它,你会使用其他的地方。

51

想一想的一种方法是:Lookup<TKey, TElement>Dictionary<TKey, Collection<TElement>>类似。基本上可以通过同一个键返回零个或多个元素的列表。

namespace LookupSample 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> names = new List<string>(); 
      names.Add("Smith"); 
      names.Add("Stevenson"); 
      names.Add("Jones"); 

      ILookup<char, string> namesByInitial = names.ToLookup((n) => n[0]); 

      // count the names 
      Console.WriteLine("J's: {0}", namesByInitial['J'].Count()); 
      Console.WriteLine("S's: {0}", namesByInitial['S'].Count()); 
      Console.WriteLine("Z's: {0}", namesByInitial['Z'].Count()); 
     } 
    } 
} 
+2

查找结果中可以有零个元素吗?你会怎么做到的? (据我所知,查找是公开的不可变的,我认为ToLookup不会有效地发明密钥。) – 2009-09-10 05:32:14

+8

从技术上讲,是的,因为Lookup为不存在的键返回空集合(我编辑了我的帖子以添加显示这个的代码示例)。 – bobbymcr 2009-09-10 05:49:12

5

我想你可以这样争论:想象你正在创建一个数据结构来保存电话簿的内容。你想按lastName键,然后按firstName键。在这里使用字典会很危险,因为很多人可以拥有相同的名字。因此,一本词典至多会映射到一个单一的值。

查找将映射到可能的几个值。

查询[“史密斯”] [“约翰”]将是一个大小10亿的集合。

+0

您的回答激发了我的后续问题[“HowLoopup()与多个索引?”](http://stackoverflow.com/questions/15734454/how-tolookup-with-multiple-indexes)。我怎么能重现这样的,与多个索引,查找?你可以使用任何其他样本或引用来回答吗?在哪里可以使用'Lookup [“Smith”] [“John”]'? – Fulproof 2013-04-01 03:27:50

17

Lookup的一种用法可能是颠倒Dictionary

假设您的电话簿实现为Dictionary,并且有一些(唯一)名称作为键,每个名称都与电话号码关联。但是名称不同的两个人可能共享相同的电话号码。这对Dictionary不是问题,它不关心两个键对应相同的值。

现在,您需要一种查找给定电话号码所属的人的方式。您构建Lookup,将Dictionary中的所有KeyValuePairs添加到其中,但向后添加的值为键和键为值。您现在可以查询电话号码,并获取所有电话号码为的人员的名单。(或失败取决于你是如何做到的)大楼内,以相同的数据Dictionary会丢弃数据,因为这样做

dictionary["555-6593"] = "Dr. Emmett Brown"; 
dictionary["555-6593"] = "Marty McFly"; 

意味着第二项覆盖第 - 的文档不再一一列出。

试图在一个稍微不同的方式来写相同的数据:

dictionary.Add("555-6593", "Dr. Emmett Brown"); 
dictionary.Add("555-6593", "Marty McFly"); 

会抛出一个异常,在第二行,因为你不能Add关键是已经在Dictionary

[当然,您可能希望使用其他单一数据结构在两个方向上执行查找等。此示例意味着每次后者更改时都必须从Dictionary重新生成Lookup。但对于一些数据可能是正确的解决方案。]

相关问题