Linq Distinct across multiple tables?
The below linq resuired is too jedi for my brain, is what im trying to do even possible?
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 l开发者_高级运维inq to only get item(s) present in each table** i.e. result = {"2"}
var result = dd.Aggregate<IEnumerable<string>>((a, x) => a.Intersect(x));
If you want slightly better theoretical performance, at the expense of some readability, then you can do the following instead. It avoids the need to construct a new set for each intersection operation, using an explicit HashSet<T>
to the pass the result to the next iteration rather than a plain 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;
});
There may be a niftier way, but you can build a query in a loop:
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]);
}
You could use the set operators - Union, Intersect etc.
(edit - misread question!)
I believe Intersect gives you what you're after straight out of the box:
var dd = aa.Intersect(bb).Intersect(cc);
Note that that will work because aa bb and cc are already all IEnumerables of the same type. If your IEnumerables are of different types (like from different Linq tables) you'll have to project the property you want:
var dd = aa.Select(a => a.PropertyA).Intersect(bb.Select(b => b.PropertyB).Intersect(cc.Select(c => c.PropertyC);
The result there will be an IQueryable, so you could chain on ToArray(), ToList() etc on the end to give the result you want.
Caution, if you are using LINQ to SQL and you cast any part of a composite query to IEnumerable<>, that part cannot be combined with the rest of the query to form a single SQL query. This would happen using SQL as the datasource in the example by spender where the query is implicitly cast to IEnumerable<> when it is assigned to 'q'. Use IQueryable instead. Although each IEnumerable is deferred, three SQL queries will be sent to the server, and the intersection will be performed in-memory.
See Returning IEnumerable<T> vs. IQueryable<T> or search "IEnumerable vs IQueryable" to get references.
Why not use a simple join?
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();
}
}
精彩评论