【发布时间】:2016-04-01 18:40:11
【问题描述】:
我有一个包含在 SortedDictionary 中的节点类:
SortedDictionary<Node, bool> openList = new SortedDictionary<Node, bool>();
我需要在节点上编写 CompareTo 方法,以便节点根据一个 int 值(F)从低到高排序。我还需要能够根据节点的位置检查字典中是否已经存在节点(这个位置是使节点唯一的原因)。 CompareTo 看起来像这样:
public int CompareTo(Node other)
{
if (GridPosition != other.GridPosition)
{
if (F > other.F)
{
return 1;
}
if (F < other.F)
{
return -1;
}
return -1;
}
return 0;
}
问题是,它并不总是返回正确的结果。例如,即使节点在字典中,以下代码行也会返回 false。但是,它会完全按照我的需要对我添加到字典中的所有节点进行排序。
Node node = new Node(); //It has a grid position and a f value
openList.add(node, false);
if(openList.Keys.Contains(node)) //this returns false
{
}
为了解决这个问题,我创建了一个 EqualityComparer 并在比较值时使用它。相等比较器如下所示:
class NodeEqualityComparer : IEqualityComparer<Node>
{
public bool Equals(Node x, Node y)
{
return x.GridPosition == y.GridPosition;
}
public int GetHashCode(Node obj)
{
return obj.GridPosition.GetHashCode();
}
}
我在 SortedDictionary 的 Contains 方法中使用这个相等比较器作为参数,这很好用,它会根据 Dictionary 中的内容返回正确的结果:
if (openList.Keys.Contains(currentNode,new NodeEqualityComparer())) //This will return true if the node is in the dictionary
{
}
当我需要从字典中删除一个节点时,就会出现问题。 remove 函数使用 Node 上的 CompareTo 方法来查找要删除的节点,正如我之前所说,这个函数在比较对象时显然不会返回正确的结果。这意味着下面的代码不会 100% 地从字典中删除节点。您不能将equalComparer 传递给remove 函数,因此无法解决我的问题。
Node node = new Node(); //It has a grid position and a f value
openList.add(node, false);
openList.Remove(node);
也许我以错误的方式处理这个问题,所以如果有人对解决这个问题有一些建议,我会很高兴听到他们的意见。或许我可以写一个CompareTo函数来解决这个问题?
【问题讨论】:
-
您应该在 if 语句的末尾返回 0 而不是 -1。您应该始终确保
A.CompareTo(B)与B.CompareTo(A)相反。 -
如果我在 if 语句之后返回 0,它将不允许我在字典中有两个具有相同 F 值的节点。
-
那你需要扩大你的比较。你应该始终遵循我在第一条评论中写的规则,排序算法依赖于它,如果你不这样做,不要对排序算法做奇怪的事情感到惊讶。
-
问题是你已经用“是”回答了这个问题:“A 还是 B 应该先来”。这不是这个问题的好答案。
-
是的,我知道我会看看我能不能把头绕过去 :)
标签: c# dictionary collections iequalitycomparer icomparer