Lookup <TKey,TElement>有什么意义?

dan*_*gph 144 .net c# linq lookup

MSDN解释了这样的Lookup:

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

我没有发现这种解释特别有用.Lookup用于什么?

Jon*_*eet 207

它是一个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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(我通常var在普通代码中使用大多数声明.)

  • 我想更好地回答这个问题,你可以更换一些变量.出于学习目的,我认为在明确表达类型时更容易理解.只是我的2美分:) (54认同)
  • @KyleBaran:因为真正的键/值对集合是没有意义的,每个键只有一个值. (14认同)
  • @KyleBaran`Lookup <,>`只是一个不可变的集合(例如没有`Add`方法),它的用途有限.此外,它不是通用集合,在某种意义上,如果你对不存在的键进行查找,则会得到一个空序列而不是异常,这仅在特殊情境中有意义,例如,使用linq.这与MS没有为该类提供公共构造函数这一事实很顺利. (10认同)
  • 如果它拥有两全其美,那么为什么要费心去做词典? (3认同)

bob*_*mcr 56

考虑它的一种方法是: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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,是的,因为Lookup为不存在的键返回一个空集合(我编辑了我的帖子以添加显示此代码的代码示例). (8认同)
  • 查找结果中可以有零元素吗?你怎么会那样?(就我所知,查找是公开不可变的,我不认为ToLookup会有效地发明密钥.) (2认同)

jwg*_*jwg 22

一个用途Lookup可能是扭转a Dictionary.

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

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

dictionary["555-6593"] = "Dr. Emmett Brown";
dictionary["555-6593"] = "Marty McFly";
Run Code Online (Sandbox Code Playgroud)

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

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

dictionary.Add("555-6593", "Dr. Emmett Brown");
dictionary.Add("555-6593", "Marty McFly");
Run Code Online (Sandbox Code Playgroud)

会在第二行引发异常,因为你不能Add使用已经存在的密钥Dictionary.

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

  • 答案对于理解这个概念至关重要。+1。阅读答案的顺序是 jwg -&gt; bobbymcr -&gt; jonskeet (2认同)

Dar*_*mas 14

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

A Lookup<TKey, TElement>表现得非常像没有唯一约束的表上的(关系)数据库索引.在您使用另一个的相同位置使用它.


Dav*_*res 5

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

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

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