LINQ - 全外部联接
问题:
给定两个包含ID以及名字或姓氏的人员列表,执行全外部联接以生成包含名字和姓氏的个人列表。
解答:
全外部联接与其他联接的不同之处在于,它包含来自两个输入列表的项,即使在另一个列表中没有匹配的元素。 为此,我们可以利用FullOuterJoin
扩展方法,其工作原理如下:
更新后的代码实现:
<code class="language-csharp">internal static class MyExtensions { internal static IEnumerable<TResult> FullOuterJoin<TA, TB, TKey, TResult>( this IEnumerable<TA> a, IEnumerable<TB> b, Func<TA, TKey> selectKeyA, Func<TB, TKey> selectKeyB, Func<TA, TB, TKey, TResult> projection, IEqualityComparer<TKey> cmp = null) { cmp = cmp ?? EqualityComparer<TKey>.Default; var alookup = a.ToLookup(selectKeyA, cmp); var blookup = b.ToLookup(selectKeyB, cmp); var keys = new HashSet<TKey>(alookup.Select(p => p.Key), cmp); keys.UnionWith(blookup.Select(p => p.Key)); var join = from key in keys let xa = alookup[key].DefaultIfEmpty(default(TA)) let xb = blookup[key].DefaultIfEmpty(default(TB)) select projection(xa.FirstOrDefault(), xb.FirstOrDefault(), key); return join; } }</code>
示例用法:
<code class="language-csharp">var ax = new[] { new { id = 1, name = "John" }, new { id = 2, name = "Sue" } }; var bx = new[] { new { id = 1, surname = "Doe" }, new { id = 3, surname = "Smith" } }; ax.FullOuterJoin(bx, a => a.id, b => b.id, (a, b, id) => new { a?.name, b?.surname, id }) .ToList().ForEach(Console.WriteLine);</code>
这段代码将输出以下结果:
<code>{ name = John, surname = Doe, id = 1 } { name = Sue, surname = , id = 2 } { name = , surname = Smith, id = 3 }</code>
This revised answer uses FirstOrDefault()
to handle the potential null values from DefaultIfEmpty()
more gracefully and directly outputs the name and surname, along with the ID, making the result clearer. The ?.
null-conditional operator prevents exceptions if a
or b
are null.
以上是如何在LINQ中执行完整的外部加入以根据ID合并两个人列表?的详细内容。更多信息请关注PHP中文网其他相关文章!