【问题标题】:Linq - Find Missing values in a List<> - Terribly inefficientLinq - 在列表中查找缺失值<> - 效率极低
【发布时间】:2016-04-25 16:54:04
【问题描述】:

假设我的 C# 程序中有一个如下定义的类:

class MyClass
{
    public string ID;
    public int Val;
    public DateTime StartDate;
    public DateTime EndDate;
}

我的程序中有一个巨大的List&lt;MyClass&gt;,我需要检查此列表中是否有任何值:

  1. 满足特定的一组标准(在这个简化的例子中,假设Val != 0,但标准比这复杂得多)
  2. 列表中有一个对应的值(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&lt;DateTime,Dictionary&lt;int,MyClass&gt;&gt;,其中外部的键是 StartDate。然后,您只需获取所有具有正确 startdate 和 TryGetValue() 的 ID 即可。当然,这一切都需要时间来设置,但没有冗余。 (其实没关系——这是对 Servy 在下面的回答中所建议的内容的拼凑模仿;我以前从未听说过 ToLookup)。
  • @EdPlunkett 与其将一个字典嵌套在另一个字典中,不如使用一个具有多个参数的键的字典更有效(在时间和空间上)。并且使用ILookup(这是一个与Dictionary 非常相似的结构使代码更加简洁,因为它支持键的重复值(这对我们来说很好)并允许我们传递一个不存在的键更干净。
  • @Servy "TIL",正如他们所说。谢谢。

标签: c# linq


【解决方案1】:

您需要创建一个基于哈希的查找结构来查找具有给定值的项目,而不是通过一个大列表对每个项目进行线性搜索。

var lookup = myTest.Where(ItemIsValid)
    .ToLookup(item => new
    {
       item.ID,
       Date = item.EndDate,
    });

然后您可以查看您的其他收藏,看看您是否可以在查找中找到匹配项:

var query = expectDt1.Where(item => !lookup[new {item.ID, Date = item.StartDate}].Any());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多