【发布时间】:2012-12-03 01:48:31
【问题描述】:
我在 C# 4.0 中有一个分层对象的HashSet<T>。主键是 int,但偶尔会有重复的辅助键。我想将条目与重复的辅助键合并。在此示例中,辅助键是名称:
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",...},然后更新并合并其他剩余元素中的 Parent 和 Children 引用;最终结果应该是这样的:
{ 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 方法来防止重复。
【问题讨论】:
-
整数ID是干什么用的?您可以使用 Dictionary
字符串是水果名称吗? -
在此处使用
HashSet不会为您的算法或解决方案增加任何价值。Elements 需要实现GetHashCode和Equals,但是由于您的密钥甚至不是Element,所以它完全没用。您可以通过Dictionary<int, Element>获得更好的结果,其中密钥与Element.ID相同。 -
var copy = Elements;不创建副本。只是对同一件事的另一个引用。 -
@SinaIravanian 不太满足需要,他需要一个复合键。也许将子信息分离到单独的记录中,并将密钥作为实际元素的一部分进行维护?
-
@jcolebrand 我认为他可以通过为
Element结构实现GetHashCode和Equals来实现创建复合键。只需检查需要相同的字段。
标签: c# linq .net-4.0 duplicates hashset