.net 查找〈TKey,TElement>的意义是什么?

o2rvlv0m  于 2023-01-14  发布在  .NET
关注(0)|答案(6)|浏览(133)

MSDN对查找的解释如下:
Lookup<TKey, TElement>类似于Dictionary<TKey, TValue>,区别在于**Dictionary〈TKey,TValue〉将键Map到单个值,而Lookup〈TKey,TElement〉**将键Map到值的集合。
我不觉得这个解释有什么特别的帮助。查找是用来做什么的?

x3naxklr

x3naxklr1#

它是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来进行大多数声明。)

brjng4g3

brjng4g32#

我们可以这样想: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
        }
    }
}
3z6pesqy

3z6pesqy3#

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中的键。
[Of当然,您可能希望使用其他一些单一数据结构来执行双向查找等。此示例意味着每次Dictionary发生变化时,您都必须从Dictionary重新生成Lookup。但对于某些数据,这可能是正确的解决方案。]

ppcbkaq5

ppcbkaq54#

我以前没有成功地使用过它,但现在我开始了:
Lookup<TKey, TElement>的行为非常类似于没有唯一约束的表上的(关系)数据库索引,在相同的地方使用它。

6vl6ewon

6vl6ewon5#

我想你可以这么说:假设你正在创建一个数据结构来保存电话簿的内容。你想先按lastName键,然后按firstName键。在这里使用字典是危险的,因为许多人可能有相同的名字。因此,字典最多总是Map到一个值。
查找可能Map到多个值。
查找[“Smith”][“John”]将是大小为十亿的集合。

zqdjd7g9

zqdjd7g96#

补充更多:
ToLookup是立即执行的,会将结果缓存到内存中。但是GroupBy是延迟执行的,不会缓存分组结果,每次调用它时都会重新分组。
如果你需要重复访问一个“分组固定数据”,你应该选择ToLookUp来获得一个LookUp Instance,特别是当数据量很大或者多次访问数据时,使用GroupBy会导致严重的性能问题--ToLookUp以使用更多内存为代价,缓存的分组结果会给你的代码带来更好的性能。
顺便说一句:LookUp有时可以用作“EasyDictionary”,因为它不会在不存在的键上抛出异常。

相关问题