繁体   English   中英

Lookup 的意义是什么<tkey, telement> ?</tkey,>

[英]What is the point of Lookup<TKey, TElement>?

MSDN 是这样解释 Lookup 的:

Lookup<TKey, TElement>类似于Dictionary<TKey, TValue> 区别在于Dictionary<TKey, TValue>将键映射到单个值,而Lookup<TKey, TElement>将键映射到 collections 个值。

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

它是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 。)

考虑它的一种方法是: 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
        }
    }
}

Lookup一个用途可能是反转Dictionary

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

现在,您想要一种查找给定电话号码所属的人的方法。 构建一个Lookup ,从Dictionary添加所有KeyValuePairs ,但是向后,将值作为键,将键作为值。 您现在可以查询电话号码,并获取电话号码所有人的姓名列表。 使用相同的数据构建Dictionary会丢弃数据(或失败,具体取决于您的操作方式),因为这样做

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的键。

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

我之前没有成功使用它,但这是我的去处:

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

我想你可以这样说:想象你正在创建一个数据结构来保存电话簿的内容。 您想要通过lastName键入,然后键入firstName。 在这里使用字典会很危险,因为许多人可以使用相同的名称。 因此,词典总是最多映射到单个值。

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

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

补充更多:
ToLookup是立即执行,会将结果缓存到memory。而GroupBy是延迟执行,不会缓存分组结果,每次调用时都会重新分组。
如果你需要重复访问一个“分组固定数据”,你应该选择ToLookUp来获取一个LookUp Instance。
顺便说一句: LookUp有时可以用作“EasyDictionary”,因为它不会在不存在的键上抛出异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM