【发布时间】:2016-04-25 16:54:04
【问题描述】:
假设我的 C# 程序中有一个如下定义的类:
class MyClass
{
public string ID;
public int Val;
public DateTime StartDate;
public DateTime EndDate;
}
我的程序中有一个巨大的List<MyClass>,我需要检查此列表中是否有任何值:
- 满足特定的一组标准(在这个简化的例子中,假设
Val != 0,但标准比这复杂得多) - 列表中有一个对应的值(
IDs 匹配),StartDate等于当前值的EndDate
我目前的代码如下:
var myTest = new List<MyClass>();
... populate myTest ...
var expectDt1 = myTest
.Where(v => v.Val != 0)
.Select(v => new {ID = v.ID, EndDate = v.EndDate});
var dontExist = expectDt1
.Where(tst =>
!myTest.Any(v =>
v.ID.Equals(tst.ID)
&& v.StartDate == tst.EndDate
)
);
此代码有效,但运行速度非常慢(我的列表中有数千个条目)。有没有更好的方法(分组或其他)可以提高效率?
(PS - 我知道我可以把它变成一个更简化的 Linq 语句,而不需要中间的 expectedDt1 变量,但这对效率没有帮助,所以我只是这样写,让我的问题更容易理解)
【问题讨论】:
-
可能您为此选择了错误的数据结构。您能否详细说明有多少条记录、hom many !=0、多少重复 id 等?
-
我会尝试将列表填充到
Dictionary<DateTime,Dictionary<int,MyClass>>,其中外部的键是 StartDate。然后,您只需获取所有具有正确 startdate 和 TryGetValue() 的 ID 即可。当然,这一切都需要时间来设置,但没有冗余。 (其实没关系——这是对 Servy 在下面的回答中所建议的内容的拼凑模仿;我以前从未听说过 ToLookup)。 -
@EdPlunkett 与其将一个字典嵌套在另一个字典中,不如使用一个具有多个参数的键的字典更有效(在时间和空间上)。并且使用
ILookup(这是一个与Dictionary非常相似的结构使代码更加简洁,因为它支持键的重复值(这对我们来说很好)并允许我们传递一个不存在的键更干净。 -
@Servy "TIL",正如他们所说。谢谢。