Using LINQ I have a list of lists, how can I select all the objects that exist in each list?
I have a list of lists:
List<Tuple<string, List<SomeObject>>
I want to select all SomeObjects
that exist in all rows of the list above.
Some will only exist in one or two lists, but I want all objects to exist in each separate list and the rest of the objects to be discarded.
I cannot find an elegant solution without a bunch of C # code. Is there a good way?
source to share
Strongly inspired by Juan Lopez's beautiful answer, you can define this extension:
static IEnumerable<TSource> IntersectMany<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
{
return sources.Aggregate(Enumerable.Intersect);
}
then this works:
var result = list.Select(x => x.Item2).IntersectMany();
This works because it IEnumerable<out T>
is covariant in T
(C # 4, .NET 4.0).
source to share
Assuming the class overrides Equals
+ GetHashCode
or you have a custom one IEqualityComparer<SomeObject>
, you can use the following query, which uses Enumerable.All
:
var result = list
.SelectMany(t => t.Item2) // select all objects
.Distinct() // just an optimization since duplicates are guaranteed
.Where(obj => list.All(t => t.Item2.Contains(obj)));
Here's my details:
var list = new List<Tuple<string, List<SomeObject>>>();
list.Add(Tuple.Create("a", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 4 } }));
list.Add(Tuple.Create("b", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 3 } }));
list.Add(Tuple.Create("c", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 3 } }));
list.Add(Tuple.Create("d", new List<SomeObject> { new SomeObject { ID = 1 }, new SomeObject { ID = 2 }, new SomeObject { ID = 3 } }));
Only tags SomeObjects
with ID = 1 or ID = 2 are found in all lists and that's the result of the query.
source to share