Linq区分多个表?

时间:2011-01-10 09:46:11

标签: c# linq

以下的linq对我的大脑来说太过绝对,是我试图做的甚至可能吗?

var aa = new string[] { "1", "2" };
var bb = new string[] { "1", "2", "3" };
var cc = new string[] { "2" };

//*cannot directly reference the above anymore*//
var dd = new string[][] { aa, bb, cc };
//result = dd.**magical linq to only get item(s) present in each table** i.e. result = {"2"}

5 个答案:

答案 0 :(得分:3)

可能有更简单的方法,但您可以在循环中构建查询:

var aa = new string[] { "1", "2" };
var bb = new string[] { "1", "2", "3" };
var cc = new string[] { "2" };

var dd=new string[][] { aa, bb, cc };

IEnumerable<string> q=dd.First();

for(var i=1;i<dd.Length;++i)
{
    q=q.Intersect(dd[i]);
}

答案 1 :(得分:3)

var result = dd.Aggregate<IEnumerable<string>>((a, x) => a.Intersect(x));

如果你想要稍微好一点的理论性能,而牺牲一些可读性,那么你可以做以下事情。它避免了为每个交集操作构造新集合的需要,使用显式HashSet<T>将结果传递给下一个迭代而不是普通IEnumerable<T>

var result = dd.Aggregate((HashSet<string>)null,
                          (a, x) => {
                                        if (a == null)
                                            a = new HashSet<string>(x);
                                        else
                                            a.IntersectWith(x);
                                        return a;
                                    });

答案 2 :(得分:3)

您可以使用集合运算符 - Union,Intersect等。

(编辑 - 误读问题!)

我相信Intersect会为您提供开箱即用的内容:

var dd = aa.Intersect(bb).Intersect(cc);

请注意,这将起作用,因为ab和cc已经是相同类型的所有IEnumebles。如果您的IEnumerables属于不同类型(例如来自不同的Linq表),您将需要投影所需的属性:

var dd = aa.Select(a => a.PropertyA).Intersect(bb.Select(b => b.PropertyB).Intersect(cc.Select(c => c.PropertyC);

结果会有一个IQueryable,所以你可以在末尾链接ToArray(),ToList()等,以得到你想要的结果。

答案 3 :(得分:3)

注意,如果您使用LINQ to SQL并将复合查询的任何部分强制转换为IEnumerable&lt;&gt;,则该部分不能与查询的其余部分组合以形成单个SQL查询。这将通过使用SQL作为示例中的数据源通过spender发生,其中查询被隐式地转换为IEnumerable&lt;&gt;当它被分配给'q'时。请改用IQueryable。尽管每个IEnumerable都是延迟的,但是三个SQL查询将被发送到服务器,并且交集将在内存中执行。

请参阅Returning IEnumerable<T> vs. IQueryable<T>或搜索“IEnumerable vs IQueryable”以获取参考资料。

答案 4 :(得分:0)

为什么不使用简单的连接?

class Program
{
    static void Main(string[] args)
    {
        var aa = new string[] { "1", "2", "4" };
        var bb = new string[] { "1", "2", "3", "4" };
        var cc = new string[] { "2", "4" };

        //*cannot directly reference the above anymore*//
        var dd = new string[][] { aa, bb, cc };

        var result = dd.Aggregate((x, y) => x.Join(y, z => z, z => z, (z, v) => z).ToArray());
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
        Console.ReadLine();
    }
}