我正在收集一些线段并修剪任何重叠的部分,我应该得到一个不重叠的集合作为输出。
要测试我的输出,我想迭代集合中的每个项目,并确保它不与任何其他项目重叠。
目前我有这段代码:
foreach (var assay in compiledAssays)
{
if (compiledAssays.Where(a => a != assay).Any(a => a.Overlaps(assay)))
{
throw new ApplicationException("Something went wrong.");
}
}
它可读但对我来说“闻起来很糟糕”。似乎它将至少三次迭代整个集合来进行测试。
是否有更好的方式来表达此测试?
答案 0 :(得分:3)
好吧,合并Where
和Any
条款将是一个很好的初步改进:
foreach (var assay in compiledAssays)
{
if (compiledAssays.Any(a => a != assay && a.Overlaps(assay)))
{
throw new ApplicationException("Something went wrong.");
}
}
您还可以尝试更简洁:
if (compiledAssays.Any(a => compiledAssays.Any(b => a != b && a.Overlaps(b))))
{
throw new ApplicationException("Something went wrong."");
}
否则,如果您主要关心的是最小化执行的循环量,我不会使用Linq。我会这样做(假设compiledAssays
是一个数组,根据需要进行调整):
for (int i = 0; i < compiledAssays.Length; i++)
{
for (int j = i + 1; j < compiledAssays.Length; j++)
{
if (compiledAssays[i].Overlaps(compiledAssays[j]))
{
throw new ApplicationException("Something went wrong.");
}
}
}
编辑: Raymond Chen的一则非常恰当的评论。
我的上一个选项假定Overlaps
函数是对称的。
换句话说,a.Overlaps(b)
将始终返回与b.Overlaps(a)
相同的值。如果不是这样,那么我的最后一个选项是不正确的。
答案 1 :(得分:1)
您的第一个Where
子句排除了完全重复(取决于!=
定义的assay
),因此您可以使用compiledAssays.Distinct
作为基本枚举,但鉴于你可以使用排序来优化搜索重叠,但是以额外的循环为代价,现在接受的答案的显式双循环是好的,除了它目前不排除所有重复。它应该是:
for (int i = 0; i < compiledAssays.Length; i++)
{
for (int j = i + 1; j < compiledAssays.Length; j++)
{
if (compiledAssays[i] != compiledAssays[j]
&& compiledAssays[i].Overlaps(compiledAssays[j]))
{
throw new ApplicationException("Something went wrong.");
}
}
}
复制OP,再次假设Overlaps
是对称的。