我有一个由一些复杂表达式生成的 ILookup。假设这是按姓氏查找人。(在我们简单化的世界模型中,姓氏在家庭中是唯一的)
ILookup<string, Person> families;
Run Code Online (Sandbox Code Playgroud)
现在我有两个疑问,我对如何构建感兴趣。
首先,我如何按姓氏过滤?
var germanFamilies = families.Where(family => IsNameGerman(family.Key));
Run Code Online (Sandbox Code Playgroud)
但这里germanFamilies有一个IEnumerable<IGrouping<string, Person>>; 如果我调用ToLookup()它,我最好打赌会得到一个IGrouping<string, IGrouping<string, Person>>. 如果我想聪明点,SelectMany先打电话,我最终会发现计算机做了很多不必要的工作。如何轻松地将这个枚举转换为查找?
其次,我只想查询成年人的信息。
var adults = families.Select(family =>
new Grouping(family.Key, family.Select(person =>
person.IsAdult())));
Run Code Online (Sandbox Code Playgroud)
在这里,我面临两个问题:Grouping类型不存在(除了作为 的内部内部类Lookup),即使存在,我们也会遇到上面讨论的问题。
那么,除了完全实现 ILookup 和 IGrouping 接口,或者让计算机做大量愚蠢的工作(重新分组已经分组的内容)之外,是否有办法改变现有的 ILookups 以生成我错过的新 ILookups?
(根据您的查询,我假设您实际上想按姓氏进行过滤。)
您无法修改ILookup<T>我所知道的任何实现。正如您清楚地意识到的那样,当然可以使用不可变查找来实现ToLookup:)
但是,您可以做的是更改为使用Dictionary<string, List<Person>>:
var germanFamilies = families.Where(family => IsNameGerman(family.Key))
.ToDictionary(family => family.Key,
family.ToList());
Run Code Online (Sandbox Code Playgroud)
该方法也适用于您的第二个查询:
var adults = families.ToDictionary(family => family.Key,
family.Where(person => persion.IsAdult)
.ToList());
Run Code Online (Sandbox Code Playgroud)
虽然这仍然比我们认为必要的工作多一些,但也不算太糟糕。
编辑:评论中与 Ani 的讨论值得一读。基本上,我们已经要迭代每个人了 - 所以如果我们假设 O(1) 字典查找和插入,那么使用现有查找的时间复杂度实际上并不比扁平化更好:
var adults = families.SelectMany(x => x)
.Where(person => person.IsAdult)
.ToLookup(x => x.LastName);
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,我们可以使用现有的分组,如下所示:
// We'll have an IDictionary<string, IGrouping<string, Person>>
var germanFamilies = families.Where(family => IsNameGerman(family.Key))
.ToDictionary(family => family.Key);
Run Code Online (Sandbox Code Playgroud)
这可能会更有效(如果我们每个家庭都有很多人),但意味着我们正在“脱离上下文”使用分组。我相信这实际上没问题,但出于某种原因,它在我嘴里留下了一点奇怪的味道。当ToLookup具体化查询时,很难看出它实际上是如何出错的......
| 归档时间: |
|
| 查看次数: |
1510 次 |
| 最近记录: |