我的树结构如下:
public class TAGNode
{
public string Val;
public string Type = "";
private List<TAGNode> childs;
public IList<TAGNode> Childs
{
get { return childs.AsReadOnly(); }
}
public TAGNode AddChild(string val)
{
TAGNode tree = new TAGNode(val);
tree.Parent = this;
childs.Add(tree);
return tree;
}
public override bool Equals(object obj)
{
var t = obj as TAGNode;
bool eq = Val == t.Val && childs.Count == t.Childs.Count;
if (eq)
{
for (int i = 0; i < childs.Count; i++)
{
eq &= childs[i].Equals(t.childs[i]);
}
}
return eq;
}
}
我有一个这样的树的列表,可以包含重复的树,重复我的意思是它们具有相同的结构和相同的标签。现在我想从这个列表中选择不同的树。我试过了
etrees = new List<TAGNode>();
TAGNode test1 = new TAGNode("S");
test1.AddChild("A").AddChild("B");
test1.AddChild("C");
TAGNode test2 = new TAGNode("S");
test2.AddChild("A").AddChild("B");
test2.AddChild("C");
TAGNode test3 = new TAGNode("S");
test3.AddChild("A");
test3.AddChild("B");
etrees.Add(test1);
etrees.Add(test2);
etrees.Add(test3);
var results = etrees.Distinct();
label1.Text = results.Count() + " unique trees";
这会返回所有树木的数量(3),而我期待2棵不同的树木!我想也许我应该为它实现一个合适的Equals
函数,但是在我测试它时并不关心Equals
返回的内容!
答案 0 :(得分:2)
我想也许我应该为它实现一个合适的Equals函数
正确。
但正如我测试的那样,它并不关心Equals的回报!
因为您必须实现匹配的GetHashCode
!它不需要包含Equals
中使用的所有项目,在您的情况下Val
就足够了。请记住,您只需为可能相等的项返回一个相同的哈希码。具有不同哈希码的项目被视为不相等,并且永远不会使用Equals
进行检查。
所以这样的事情应该有效:
public bool Equals(TAGNode other)
{
if ((object)this == (object)other) return true;
if ((object)other == null) return false;
return Val == other.Val && childs.SequenceEqual(other.childs);
}
public override bool Equals(object obj) => Equals(obj as TAGNode);
public override int GetHashCode() => Val?.GetHashCode() ?? 0;
一旦你这样做,你也可以&#34;标记&#34;您的TAGNode
为IEquatable<TAGNode>
,让默认的相等比较器直接调用Equals(TAGNode other)
重载。
答案 1 :(得分:1)
请参阅https://msdn.microsoft.com/en-us/library/bb348436(v=vs.100).aspx
如果要从某些自定义数据类型的对象序列中返回不同的元素,则必须在类中实现IEquatable泛型接口。以下代码示例演示如何在自定义数据类型中实现此接口,并提供GetHashCode和Equals方法。
你需要为TagNode实现IEquatable
答案 2 :(得分:0)
尝试关注GetHashCode。我更新了下面的方法,使其更加强大。害怕原始答案可能无法创造独特的价值观。
private int GetHashCode(TAGNode node)
{
string hash = node.Val;
foreach(TAGNode child in node.childs)
{
hash += GetHashStr(child);
}
return hash.GetHashCode();
}
private string GetHashStr(TAGNode node)
{
string hash = node.Val;
foreach (TAGNode child in node.childs)
{
hash += ":" + GetHashStr(child);
}
return hash;
}