sam*_*gua -1 c# linq big-o list
我有两个包含对象元素的列表,一个大列表称为List1,另一个小列表称为List2。我需要基于在函数中定义的条件,用List2中的值更新List1中的值,该函数基于对象中的值返回布尔值。我想出了以下实现,对于较大的列表,这确实需要很多时间。
检查项目是否将被更新的功能
private static bool CheckMatch(Item item1, Item item2) {
//do some stuff here and return a boolean
}
Run Code Online (Sandbox Code Playgroud)
查询我用来更新物品
在下面的代码段中,我需要使用List2(小列表)中的一些值更新List1(大列表)
foreach(var item1 in List1)
{
var matchingItems = List2.Where(item2 => CheckMatch(item1, item2));
if (matchingItems.Any())
{
item1.IsExclude = matchingItems.First().IsExcluded;
item1.IsInclude = matchingItems.First().IsIncluded;
item1.Category = matchingItems.First().Category;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望我能得到一个比这更好的解决方案。我还需要保持元素在List1中的位置
这是我在做 什么的示例这是我在做什么的示例
正如LP13的答案所指出的那样,您将通过重新执行查询而不是一次执行并缓存结果来进行大量的重新计算。
但是,这里更大的问题是,如果您有和中有潜在匹配n项,并且您正在寻找任何匹配项,那么最坏的情况肯定是要匹配。如果和大,它们的乘积就更大。而且,由于我们正在寻找任何匹配项,因此最糟糕的情况是没有匹配项。您一定会尝试所有可能性。List1mList2n * mnmm
这个费用可以避免吗?也许,但是只有当我们知道一些可以利用的技巧,并且您使问题变得如此抽象时(我们有两个列表和一个关系,而没有关于列表或关系的信息),所以没有结构我们可以利用的。
就是说:如果您碰巧知道其中有一个元素List2可能与许多项目匹配,List1那么请将该元素放在第一位。 Any或FirstOrDefault会Where在获得第一个匹配项后停止执行查询,因此您可以将O(n * m)问题变成O(n)问题。
如果不了解关系之间的关系,就很难说如何提高性能。
更新:评论者指出,如果我们知道该关系是等价关系,我们可以做得更好。是等价关系吗?也就是说,假设我们有您的方法可以检查两个项目。我们可以保证以下内容吗?
CheckMatch(a, a)永远是对的。CheckMatch(a, b)始终与CheckMatch(b, a)CheckMatch(a, b)为true和CheckMatch(b, c)true,则CheckMatch(a, c)始终为true如果我们具备这三个条件,那么您可以做得更好。这样的关系将元素划分为等价类。你要做的就是每个项目相关联List1,并List2与规范值。对于等价类的每个成员,该规范值都是相同的。然后,您可以从该词典中进行快速查找并快速解决问题。
但是,如果您的关系不是等价关系,则此方法无效。