LINQ(to Object)查询是否可能包含无限循环?

jan*_*y02 0 c# linq linq-to-objects

我有一个简单的课程:

public class RawBomItem
{
    private string material;
    private string item;
    private string component;
    private string quantity;
    private string b;
    private string spt;
...
}
Run Code Online (Sandbox Code Playgroud)

每个数据库都有一个属性.

然后我有一个List包含这个类的实例

    private List<RawBomItem> rawBom;
Run Code Online (Sandbox Code Playgroud)

该列表包含超过70000个项目.

此时我想在此List上运行一个复杂的LINQ查询.

List<string> endProducts = new List<string>(
    rawBom.Where(x1 => new List<string>(rawBom.Select(x2 => x2.Component)
                                              .Distinct())
                           .Contains(x1.Material) && (x1.B != "F"))
          .Select(x3 => x3.Material));
Run Code Online (Sandbox Code Playgroud)

查询似乎遇到了无限循环.(我等了好几分钟然后把它关了)

我会把它变成DB工作,我只是对可能出现的问题感兴趣.

Dan*_*rth 9

我不知道应该有一个无限循环,但你的代码效率极低.
对于您中的每个项目,rawBom计算组件的不同组合并将它们复制到新列表中.因此,如果列表中包含70,000个项目,则执行70.000 ^ 2 = 4,900,000,000次迭代.此外,对于列表中的每个项目,您将再次迭代不同组件的列表.根据您拥有的不同组件数量,您可以在顶部添加相同数量的迭代.

这可以改进:

var components = new HashSet<string>(rawBom.Select(x => x.Component).Distinct());
var endProducts = rawBom.Where(x => components.Contains(x.Material) &&
                                    x.B != "F")
                        .Select(x => x.Material)
                        .ToList();
Run Code Online (Sandbox Code Playgroud)
  1. 我们从主查询中提取不同组件列表的创建,因此我们只需要计算一次 - 而不是70.000次.
  2. 我们用a HashSet<string>而不是a List<string>.这改变了呼叫ContainsO(n)O(1).

最终结果是您只列举了两次列表,结果只有140,000次迭代.现在将其与原始迭代次数进行比较.