Linq检查集合中没有项目与任何其他项目匹配的方式

时间:2015-07-24 01:53:10

标签: c# linq

我正在收集一些线段并修剪任何重叠的部分,我应该得到一个不重叠的集合作为输出。

要测试我的输出,我想迭代集合中的每个项目,并确保它不与任何其他项目重叠。

目前我有这段代码:

foreach (var assay in compiledAssays)
{
    if (compiledAssays.Where(a => a != assay).Any(a => a.Overlaps(assay)))
    {
        throw new ApplicationException("Something went wrong.");
    }
}

它可读但对我来说“闻起来很糟糕”。似乎它将至少三次迭代整个集合来进行测试。

是否有更好的方式来表达此测试?

2 个答案:

答案 0 :(得分:3)

好吧,合并WhereAny条款将是一个很好的初步改进:

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是对称的。