I have 2 lists of the same type. The left list:
var leftList = new List<Person>();
leftList.Add(new Person {Id = 1, Name = "John", Changed = false});
leftList.Add(new Person {Id = 2, Name = "Alice", Changed = false});
leftList.Add(new Person {Id = 3, Name = "Mike", Changed = false});
And the right list:
var rightList = new List<Person>();
rightList.Add(new Person {Id = 1, Name = "John", Changed = false});
rightList.Add(new Person {Id = 3, Name = "Mike", Changed = true});
rightList.Add(new Person {Id = 4, Name = "Joshi", Changed = true});
I want to do a left join, but using the value on the Changed
property from the right. Like this:
{Id = 1, Name = "John", Changed = false}
{Id = 2, Name = "Alice", Changed = false}
{Id = 3, Name = "Mike", Changed = true} // <-- true from the rightList
For this, I can't use simple Left Join, and I cannot use a Concat with GroupBy.
How can I do this with linq? Thanks.
You can use LINQ to perform a left outer join by calling the DefaultIfEmpty method on the results of a group join.
In LINQ, LEFT JOIN or LEFT OUTER JOIN is used to return all the records or elements from the left side collection and matching the elements from the right side of the collection. In LINQ, to achieve the LEFT Join behavior, it is mandatory to use the "INTO" keyword and "DefaultfEmpty()" method.
relational tables. In a LINQ query expression, join operations are performed on object collections. Object collections cannot be "joined" in exactly the same way as two relational tables.
The group join is useful for producing hierarchical data structures. It pairs each element from the first collection with a set of correlated elements from the second collection. For example, a class or a relational database table named Student might contain two fields: Id and Name .
This looks like a pretty standard left outer join scenario.
I always keep this extension method handy for left outer joins so I don't have to look up how to use the nasty query syntax (or remember wtf a GroupJoin is)...
public static class LinqEx
{
public static IEnumerable<TResult> LeftOuterJoin<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
return outer
.GroupJoin(inner, outerKeySelector, innerKeySelector, (a, b) => new
{
a,
b
})
.SelectMany(x => x.b.DefaultIfEmpty(), (x, b) => resultSelector(x.a, b));
}
}
Now you can:
leftList.LeftOuterJoin(
rightList,
lft => lft.Id,
rgt => rgt.Id,
(lft, rgt) => new Person{Id = lft.Id,
Name = lft.Name,
Changed = rgt == null ? lft.Changed : rgt.Changed})
Why don't you try a solution like this:
var query = (from left in leftList
join right in rightList on left.Id equals right.Id into joinedList
from sub in joinedList.DefaultIfEmpty()
select new Person {
Id = left.Id,
Name = left.Name,
Changed = sub == null ? left.Changed : sub.Changed }).ToList();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With