使用LINQ加入[n]个集合并查找匹配项

时间:2011-02-21 16:56:38

标签: linq collections recursion

使用LINQ我可以找到两个集合之间的匹配元素,如下所示:

        var alpha = new List<int>() { 1, 2, 3, 4, 5 };
        var beta = new List<int>() { 1, 3, 5 };

        return (from a in alpha
                join b in beta on a equals b
                select a);

我可以将其增加到三个集合,如下所示:

        var alpha = new List<int>() { 1, 2, 3, 4, 5 };
        var beta = new List<int>() { 1, 3, 5 };
        var gamma = new List<int>() { 3 };

        return (from a in alpha
                join b in beta on a equals b
                join g in gamma on a equals g
                select a);

但是如何构建一个LINQ查询,该查询将返回N个集合之间的匹配?

我在想是否每个集合都被添加到父集合中,然后使用递归循环迭代父集合,它可能有用吗?

2 个答案:

答案 0 :(得分:3)

没有必要递归 - 你可以迭代。但是,您可能会发现最好创建一个集合并每次与交叉

List<List<int>> collections = ...;

HashSet<int> values = new HashSet<int>(collections[0]);
foreach (var collection in collections.Skip(1)) // Already done the first
{
    values.IntersectWith(collection);
}

(就像BrokenGlass一样,我假设你有一些distint值,并且你真的只想找到所有集合中的值。)

如果您更喜欢不可变和懒惰的方法,可以使用:

List<List<int>> collections = ...;

IEnumerable<int> values = collections[0];
foreach (var collection in collections.Skip(1)) // Already done the first
{
    values = values.Intersect(collection);
}

答案 1 :(得分:1)

如果您只有唯一值,则可以使用Intersect:

var result = alpha.Intersect(beta).Intersect(gamma).ToList();

如果您需要保留多个不唯一的值,您可以从原始集合中排除非相交的项目作为附加步骤:

alpha = alpha.Where(x => result.Contains(x)).ToList();

要概括Intersect方法,您可以使用循环逐个执行所有交叉:

IEnumerable<List<int>> collections = new [] { alpha, beta, gamma };
IEnumerable<int> result = collections.First();
foreach (var item in collections.Skip(1))
{
    result = result.Intersect(item);
}
result = result.ToList();