170

MSDN 是这样解释 Lookup 的:

ALookup<TKey, TElement> 类似于Dictionary<TKey, TValue>. 不同之处在于 Dictionary<TKey, TValue>将键映射到单个值,而 Lookup<TKey, TElement>将键映射到值的集合。

我不觉得这个解释特别有用。查找用于什么?

4

5 回答 5

231

它是一个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在普通代码中使用大多数这些声明。)

于 2009-09-10T05:24:03.360 回答
67

一种思考方式是: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()); // 1
            Console.WriteLine("S's: {0}", namesByInitial['S'].Count()); // 2
            Console.WriteLine("Z's: {0}", namesByInitial['Z'].Count()); // 0, does not throw
        }
    }
}
于 2009-09-10T05:24:53.030 回答
33

的一种用途Lookup可能是反转 a Dictionary

假设您有一个电话簿实现为Dictionary具有一堆(唯一)名称作为键,每个名称与一个电话号码相关联。但是两个不同名字的人可能共用同一个电话号码。这对于 a 来说不是问题Dictionary,它不关心两个键对应相同的值。

现在,您需要一种查找给定电话号码所属人员的方法。您构建一个,从您的Lookup中添加所有,但向后添加,以值作为键,键作为值。您现在可以查询电话号码,并获取电话号码所在的所有人的姓名列表。用相同的数据构建一个会丢弃数据(或失败,取决于你是怎么做的),因为做KeyValuePairsDictionaryDictionary

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

表示第二个条目覆盖第一个条目 - 不再列出 Doc。

尝试以稍微不同的方式写入相同的数据:

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

将在第二行引发异常,因为您不能Add使用已经在Dictionary.

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

于 2013-07-08T11:21:05.333 回答
16

我以前没有成功使用过它,但这是我的尝试:

A 的Lookup<TKey, TElement>行为非常类似于没有唯一约束的表上的(关系)数据库索引。在您将使用另一个相同的地方使用它。

于 2009-09-10T05:24:22.320 回答
5

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

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

Lookup["Smith"]["John"] 将是一个大小为 10 亿的集合。

于 2009-09-10T05:26:03.457 回答