LINQ。执行查询需要5分钟以上的时间

我需要过滤List<object>,以便删除其他string内部不存在List<string>属性的所有项目。

我创建了这个控制台应用程序只是为了确保LINQ语法正确:

class FooBar
{
    public int Id { get; set; }
    public string ValueName { get; set; }
}

然后...

List<FooBar> foobars = new List<FooBar>
{
    new FooBar { Id = 1,ValueName = "Val1" },new FooBar { Id = 2,ValueName = "Val2" },new FooBar { Id = 3,ValueName = "Val3" },new FooBar { Id = 4,ValueName = "Val4" }
};

List<string> myStrings = new List<string>
{
    "Val1","Val3"
};

// Only keep records where ValueName is found in `myStrings`
foobars = foobars.Where(f => myStrings.Contains(f.ValueName)).ToList();

因此,这一行:

foobars = foobars.Where(f => myStrings.Contains(f.ValueName)).ToList();

恰好满足了我的要求,并且还给了我这两个记录:

{ Id = 1,ValueName = "Val1" }
{ Id = 3,ValueName = "Val3" }

很好。但是...在实际应用中,foobars有超过200k项,而myStrings有约190k。而当该LINQ行被执行时,最多需要5分钟才能完成。

我显然做错了什么。 20万条记录并不大。真正的FooBar并不是那么复杂(没有嵌套对象,只有9个属性)。

这是怎么回事?

jinwenyu2002 回答:LINQ。执行查询需要5分钟以上的时间

这里的问题是您正在做foobars.Where(f => myStrings.Contains(f.ValueName)),因此对于foobars中的每个项目,您正在检查myStrings所有个项目。

缩放为二次方。也称为O(n ^ 2),请阅读更多here。 因此,如果您有10 + 10个项目,则要进行100次检查(10 * 10),如果您有10,000 + 10,000个项目,则要进行100,000,000个检查。 就您而言,您要进行38,000次以上的检查;)

解决方案:从myStrings创建一个HashSet,然后使用Contains中的HashSet

例如替换为:

var myStringsSet = new HashSet<string>(myStrings);
foobars = foobars.Where(f => myStringsSet.Contains(f.ValueName)).ToList();

现在有10,000个项目,您将进行10,000张支票,而不是100,000张。对于您而言,这将是200,000张支票,而不是38,000张。

本文链接:https://www.f2er.com/3115070.html

大家都在问