HashSet<T>
C#4.0には階層オブジェクトがあります。メインキーはintですが、重複するセカンダリキーが存在する場合があります。重複したセカンダリキーを持つエントリをマージしたいと思います。この例では、2次キーはNameです。
struct Element
{
int ID;
string Name;
List<int> Children;
List<int> Parents;
public override int GetHashCode()
{
return ID;
}
}
HashSet<Element> elements = new HashSet<Element>();
// Example Elements
elements.Add(1, "Apple", Children = {10, 11, 12}, Parents = {13,14,15});
elements.Add(2, "Banana", Children = {20, 21, 22}, Parents = {23,24,25});
elements.Add(3, "Apple", Children = {30, 31, 32}, Parents = {33,34,35});
elements.Add(4, "Food", Children = {1, 2, 3}, Parents = {});
目標は、3番目のエントリ{3、 "Apple"、...}を削除してから、他の残りの要素の親と子の参照を更新してマージすることです。最終結果は次のようになります。
{ 1, "Apple", Children = { 10, 11, 12, 30, 31, 32 }, Parents = { 13,14,15, 33, 34, 35 }}
{ 2, "Banana", Children = { 20, 21, 22 }, Parents = { 23,24,25 }}
{ 4, "Food", Children = {1, 2}, Parents = {} }
これが私がこれまでに持っているものですが、HashSetを適切に更新するための最良の方法を見つけることができません。反復中に削除できるように、HashSetをコピーすることから始めます。まず、重複を見つけます。重複がある場合は更新したいので、コピーから削除します。それは私が立ち往生しているところです。重複を更新したら、それらを削除し、スキップリストを使用して再度処理されないようにします。
var copy = new HashSet<Element>(Elements);
HashSet<int> skip = new HashSet<int>();
foreach (var e in Elements)
{
if (!skip.Contains(e.ID)
{
var duplicates = Elements.Where(x => e.Name == x.Name && e.ID != x.ID);
if (duplicates.Any())
{
foreach (var d in duplicates)
{
// Iterate copy and update Parent and Children references
// How do I do this part?
}
// Remove the duplicates from the copied list
copy.RemoveWhere(x => duplicates.Select(x => x.ID)
.Contains(x.ID));
// Don't process the duplicates again
skip.UnionWith(duplicates);
}
}
}
return copy;
私はこの時点で立ち往生しています。また、Linqでこれを行うための巧妙な方法はありますか?
更新:リストはすでにこのようになっています。最初の内容を制御することはできません。重複を防ぐために、より優れたAddメソッドを持つ新しいラッパーを作成できると思います。