ここで一歩戻りましょう。個人を整数にキー設定する 2 つの辞書があります。ただし、相対辞書のキーを比較するのではなく、それらの値を比較しています。これは、キーが一意ではないと私に思わせます。
あなたが望むのは、両方の辞書の完全な外部結合であるように思えます:
- 個体が File1 のみに存在する場合は、File1 の個体のキーと値を使用します。
- File2 の個人のみについても同様です。
- 両方のファイルに同じ個人が (名前で) 含まれている場合は、レコードをマージします。
これは、いくつかの Linq で実現できます。これは考えられる解決策の中で最もパフォーマンスが高いわけではないことを理解してください。しかし、何が起こっているのかを理解するのは少し簡単です。
//get records from 1 that aren't in 2
var left = _Individuals1.Where(l=>!_Individuals2.Any(r=>l.Value.Name == r.Value.Name));
//get records that appear in both 1 and 2,
//using the select clause to "merge" the data you want from each side
var join = from l in _Individuals1
join r in _Individuals2 on l.Value.Name equals r.Value.Name
select new KeyValuePair<int, Individual>(l.Key, r.Value);
//get records from 2 that aren't in 1
var right = _Individuals2.Where(r=>!_Individuals1.Any(l=>l.Value.Name == r.Value.Name));
//Now, the keys from the left and join enumerables should be consistent,
//because we used the keys from _Individuals1 in both of them.
var merged = left.Concat(join).ToDictionary(x=>x.Key, x=>x.Value);
//BUT, keys from records that only existed in 2 may have duplicate keys,
//so don't trust them
var maxKey = merged.Keys.Max();
foreach(var r in right)
merged.Add(++maxKey, r.Value);
ここで示した内部結合の代わりに左結合を生成するように「結合」を生成するクエリを構造化することで、列挙可能な「左」を明示的に作成することを避けることができます。マージされたディレクトリに対して各キーをチェックして、_Individuals2 のキーを使用することもできます。そのコードは次のようになります。
var maxKey = merged.Keys.Max();
foreach(var r in right)
if(merged.ContainsKey(r.Key))
merged.Add(++maxKey, r.Value);
else
{
merged.Add(r.Key, r.Value);
maxKey = r.Key > maxKey ? r.Key : maxKey;
}
これにより、キーが重複しない場合は常に _Individuals2 からのキーが安全に使用されるため、_Individuals2 からのいくつかの (おそらくすべてではない) キーを使用する必要があります。これが「より良い」かどうかは、正確な状況によって異なります。