Reputation: 11
I have 2 different IEnumerables:
IEnumerable<TypeA> ListA
& IEnumerable<TypeB> ListB
Both types have the property called "PersString".
My goal is to get for each item in ListA the corresponding items of ListB with the same "PersString".
I started with a ForEach-Loop in ListA nesting a ForEach-Loop of ListB and checking if "PersString" of the ListA-item matches the "PersString" of the ListB-item.
Is there a more efficient way of coding using Linq ?
Thank you.
Upvotes: 1
Views: 321
Reputation: 28988
In addition to Enumerable.Join
, LINQ offers the Enumerable.Intersect
method and since .NET 6 the more convenient and powerful Enumerable.IntersectBy
.
In case of Enumerable.Intersect
, more complex types require you to provide an IEqualityComparer<T>
implementation or let the data type itself implement IEquatable<T>
to define equality of this type.
Intersect
(Prior to .NET 6):Does not support comparison of two sets of different type.
class Person : IEquatable<Person>
{
public bool Equals(Person p) => this.PersString == p?.PersString;
public override int GetHashCode() => HashCode.Combine(PersString);
public int ID { get; set; }
public string PersString { get; set; }
}
IEnumerable<Person> collectionA;
IEnumerable<Person> collectionB;
IEnumerable<Person> equalPersonInstances = collectionA.Intersect(collectionB);
// In case the compared type does not implement IEquatable, we would have to provide an IEqualityComparer
// IEnumerable<Person> equalMyTypeInstances = collectionA.Intersect(collectionB, new MyComparer());
IntersectBy
(.NET 6 and later):Since .NET 6 we can use the ...By
methods to pass in a lambda expression or method group as equality comparer. In this case we call Enumeable.IntersectBy
, which supports to find the intersection of two sets of different type.
IEnumerable<PersonA> collectionA;
IEnumerable<PersonB> collectionB;
IEnumerable<PersonA> intersection = collectionA.IntersectBy(
collectionB.Select(personB => personB.PersString),
personA => personA.PersString);
Join
(using LINQ Enumerable
extension method)For those who prefer to use the LINQ extension methods:
IEnumerable<PersonA> collectionA;
IEnumerable<PersonB> collectionB;
// The result is a set of ValueTuple
IEnumerable<(Person, PersonB)> intersection = collectionA.Join(
collectionB,
personA => personA.PersString,
personB => personB.PersString,
(personA, personB) => (personA, personB));
Upvotes: 1
Reputation: 3365
Join is more efficient way
var result = from x in ListA
join y in ListB
on x.PersString equals y.PersString
select new {x,y};
Upvotes: 0
Reputation: 460158
Is there a more efficient way of coding using Linq ?
Yes, you can join them. In Linq-To-Object this is (much) more efficient:
var query = from a in ListA
join b in ListB on a.PersString equals b.PersString
select (A: a, B: b);
Upvotes: 2