左连接两个列表并使用Linq从右侧维护一个属性

Ren*_*újo 10 c# linq

我有2个相同类型的列表.左侧列表:

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});
Run Code Online (Sandbox Code Playgroud)

正确的清单:

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});
Run Code Online (Sandbox Code Playgroud)

我想做一个左连接,但是使用右边Changed属性的值.像这样:

{Id = 1, Name = "John", Changed = false}
{Id = 2, Name = "Alice", Changed = false}
{Id = 3, Name = "Mike", Changed = true} // <-- true from the rightList
Run Code Online (Sandbox Code Playgroud)

为此,我不能使用简单的Left Join,而且我不能将Concat与GroupBy一起使用.

我怎么能用linq做到这一点?谢谢.

spe*_*der 13

这看起来像一个非常标准的左外连接方案.

我总是保持这个扩展方法方便左外连接所以我不必查找如何使用讨厌的查询语法(或记住wtf一个GroupJoin)...

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以:

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})
Run Code Online (Sandbox Code Playgroud)


use*_*689 6

为什么不尝试这样的解决方案:

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();
Run Code Online (Sandbox Code Playgroud)