公開キーフィールドに基づいて2つのオブジェクト間の完全な接続を実行して、2つのリストのすべてのレコードが別のリストに対応する一致アイテムが含まれていなくても。
回答:
1。外部全体に接続されたカスタム拡張メソッド
LINQで外側の接続を実現するために、以下に示すようにカスタム拡張方法を定義できます。と
。外側の接続を実行するには、次のコードを使用できます。<code class="language-csharp">public 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, TA defaultA = default(TA), TB defaultB = default(TB), 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 from xa in alookup[key].DefaultIfEmpty(defaultA) from xb in blookup[key].DefaultIfEmpty(defaultB) select projection(xa, xb, key); return join; }</code>
の各レコードは、一致するアイテムが見つからない場合、接続がデフォルト値に接続されています。 firstNames
このステートメントは、lastNames
マッチングレコードの一時的なコレクションを作成し、
<code class="language-csharp">var outerJoin = from first in firstNames join last in lastNames on first.ID equals last.ID into temp from last in temp.DefaultIfEmpty() select new { id = first != null ? first.ID : last.ID, firstname = first != null ? first.Name : string.Empty, surname = last != null ? last.Name : string.Empty };</code>拡張方法を使用する必要があります。
firstNames
外側の接続の予想出力は次のとおりです。
lastNames
into temp
5。定義されたデフォルト値lastNames
DefaultIfEmpty()
拡張法により、不十分なレコードのデフォルト値を指定できます。この例では、不十分な名前のFullOuterJoin
を指定し、非一致IDの負の整数を指定します。
外部接続全体の実行時間はo(n m)で、nとmは2つの入力リストの長さです。これは、
操作にはO(n)時間が必要であり、その後の操作にはO(n m)時間が必要なためです。<code>ID FirstName LastName -- --------- -------- 1 John Doe 2 Sue 3 Smith</code>
外側の接続全体のこの実装は現在、LINQ標準の一部ではありませんが、将来のバージョンに含めることをお勧めします。 標準のLINQは外部接続を直接サポートせず、それを達成するためにカスタマイズする必要があります。 string.Empty
以上がLINQで完全な外側結合を実行する方法は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。