Linq Expression Slow - 尽可能优化

时间:2014-06-21 10:58:49

标签: c# performance linq time-complexity

我有一个整数列表“numberRangeList”,按顺序包含从62到92的31个整数,我提取第二个整数列表“extractedList”,它将包含10个整数,其总和等于“total”。问题是计算需要大约30秒,有没有办法加速这个?

        var numberRangeList = new List<int>() { 62, 63, ...92 };
        var total = 772;
        var extractedList= (from n1 in numberRangeList
                      from n2 in numberRangeList
                      from n3 in numberRangeList
                      from n4 in numberRangeList
                      from n5 in numberRangeList
                      from n6 in numberRangeList
                      from n7 in numberRangeList
                      from n8 in numberRangeList
                      from n9 in numberRangeList
                      from n10 in numberRangeList
                      where n1 + n2 + n3 + n4 + n5 + n6 + n7 + n8 + n9 + n10 == total
                      select new List<int> { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10 }).Take(1).First();

3 个答案:

答案 0 :(得分:4)

性能问题不在LINQ中,而在于问题本身。 这个问题在CS文献中是众所周知的,它被称为子集和http://en.wikipedia.org/wiki/Subset_sum_problem。它是属于NP完全时间复杂度类(http://en.wikipedia.org/wiki/NP-complete)的已知问题。如果您不想探索(指数)问题的复杂性,您应该对次优解决方案进行一些研究。

答案 1 :(得分:1)

在我看来,您的查询会计算从公共号码池中获取的10个号码的所有可能组合。 (或者,在数据库术语中,您正在计算一个非常大的交叉产品。)这是很多可能要处理的组合。也许并不奇怪,只需要30秒才能找到第一场比赛。

如果我没有彻底弄错,你的计算就像所谓的Knapsack problem。如果是这样,也许你可以通过研究这个众所周知的问题来找到优化。

更新:根据@Saverio Terracciano的评论,将您的问题视为背包问题的实例可能会引入比严格要求更复杂的问题。或许也可以查看sub-set problem

答案 2 :(得分:1)

问题不在于LINQ查询 - 问题在于你的算法复杂度为O(n ^ 10) - 大约有(92-62 + 1)^ 10个操作完成 - 甚至还有很多工作要做对于现代cpu。您可以使用Knapsack动态编程算法解决您的问题,然后使用BFS(广度优先搜索)来查找包含十个数字的结果。