简体   繁体   English

无法从SortedDictionary C#中删除对象

[英]Can't remove object from SortedDictionary C#

I have a node class which is contained in a SortedDictionary: 我有一个包含在SortedDictionary中的节点类:

SortedDictionary<Node, bool> openList = new SortedDictionary<Node, bool>();

I need to write the CompareTo method on the node, so that the nodes are sorted from lowest to highest based on an int value(F). 我需要在节点上编写CompareTo方法,以便根据int value(F)从最低到最高对节点进行排序。 I also need to be able to check if a node already exists in the dictionary based on their position (this position is what makes the node Unique). 我还需要能够根据其位置检查字典中是否已存在某个节点(此位置使节点具有唯一性)。 The CompareTo looks like this: 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;
}

The problem is, that it doesn't always return the correct result. 问题是,它并不总是返回正确的结果。 For example, the following line of code will return false even though the node is in the dictionary. 例如,即使节点在字典中,下面的代码行也将返回false。 However it sorts all the nodes that I add to the dictionary exactly as I want it. 但是,它会完全按照我的需要对添加到字典中的所有节点进行排序。

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
{

} 

To fix this I created an EqualityComparer and used it while comparing the values. 为了解决这个问题,我创建了一个EqualityComparer并在比较值时使用了它。 The equality comparer looks like this: 相等比较器如下所示:

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();
    }
}

I'm using this equality comparer as a parameter in the Contains method on the SortedDictionary, this works fine and it returns the correct result based on the content in the Dictionary: 我将此相等比较器用作SortedDictionary的Contains方法中的参数,此方法工作正常,并根据Dictionary中的内容返回正确的结果:

if (openList.Keys.Contains(currentNode,new NodeEqualityComparer())) //This will return true if the node is in the dictionary
{

}

The problem occours when I need to remove a node from the Dictionary. 当我需要从字典中删除一个节点时,就会出现问题。 The remove function is using the CompareTo method on the Node to find the node to remove, and as I stated earlier, this function appreantly doesn't return the correct result when comparing the objects. remove函数使用Node上的CompareTo方法来查找要删除的节点,并且正如我之前所说,该函数在比较对象时显然不会返回正确的结果。 This means that the code below will not remove the node from the dictionary 100% of the time. 这意味着下面的代码不会100%地将节点从字典中删除。 You can't pass an equalityComparer to the remove function, so that can't fix my problem. 您无法将equalsComparer传递给remove函数,因此无法解决我的问题。

   Node node = new Node(); //It has a grid position and a f value
    openList.add(node, false);
    openList.Remove(node);

Maybe I'm handeling this in a wrong way, so if anyone have some suggestions for solving this problem I'll be very happy to hear them. 也许我以错误的方式处理此问题,因此,如果有人对解决此问题有任何建议,我将很高兴听到他们的建议。 Maybe I can write a CompareTo function that solves the problem? 也许我可以编写一个CompareTo函数来解决问题?

This problem is probably a result of you comparing GridPosition in the comparer. 此问题可能是您在比较器中比较GridPosition的结果。 C# distinguishes between value types and reference types. C#区分值类型和引用类型。 If you compare two int variables the comparer will base equality on the value. 如果比较两个int变量,则比较器将基于该值等于。 For instantiated classes however the comparisson is based upon the reference, meaning you are comparing whether an object is the object in memory. 但是,对于实例化的类,比较是基于引用的,这意味着您正在比较对象是否是内存中的对象。

This: 这个:

if (GridPosition != other.GridPosition)
{

will probably almost always return true, thus resulting in your sort order being correct, because you are providing the order int he if statment nested inside: 可能几乎总是返回true,从而导致您的排序顺序正确,因为如果语句嵌套在其中,您将提供以下顺序:

if (F > other.F)
{
    return 1;
}
if (F < other.F)
{
    return -1;
}

If however (F == other.F) you assign -1 , so the ContainsKey will not recognize these objects as equal. 但是,如果(F == other.F)您分配-1 ,那么ContainsKey将不会将这些对象识别为相等。

Depending on what type GridPosition is, you should provide an appropriate comparer, for instance something like 根据GridPosition的类型,您应该提供适当的比较器,例如

if (GridPosition.X != other.GridPosition.X && GridPosition.Y != other.GridPosition.Y)

And depending on what F is, you are violating the mathematical principal of symmetry, as an object with different GridPosition and equal F will alway be sorted before any other object fulfilling this. 并且取决于F是什么,您在违反对称性的数学原理,因为具有不同GridPosition和相等F的对象将始终在其他任何满足此要求的对象之前进行排序。 Thus for two objects you could get A == B ==> -1 and B == A ==> -1 which isnt useful in any case. 因此,对于两个对象,您可以获得A == B ==> -1B == A ==> -1 ,这在任何情况下都没有用。

So you would have to do this in the nested if: 因此,如果发生以下情况,您将必须在嵌套中执行此操作:

if (GridPosition != other.GridPosition)
{
    if (F > other.F)
    {
        return 1;
    }
    if (F < other.F)
    {
        return -1;
    }
    /////////////////////////////////
    return 0;
    /////////////////////////////////
}

or expand the comparission to a third condition beyond GridPosition and F 或将比较扩展到GridPositionF以外的第三个条件

EDIT: Based on the information you provided in the comments, you don't actually want a dictionary in this case, just a list with proper sorting. 编辑:根据您在注释中提供的信息,在这种情况下,您实际上并不需要字典,只需一个具有适当排序的列表即可。 For instance: 例如:

        List<Node> myList = new List<Node>();
        myList.Sort((node1, node2) => node1.F > node2.F);//Sort the list based on their node value

As for your bool; 至于你的笨蛋; I don't know what this represents, but I'm under the strong impression that you want a regular Dictionary<Node, bool> for this. 我不知道这代表什么,但是我强烈希望您为此使用常规的Dictionary<Node, bool> Then use the list myList to handle whatever node you need as next waypoint and lookup the bool corresponding to a node in the dictionary whenever you need it. 然后使用列表myList来处理所需的任何节点作为下一个航路点,并在需要时在字典中查找与该节点相对应的布尔值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM