Comparing two dictionaries for equal data in c#?

前端 未结 5 1520
小蘑菇
小蘑菇 2021-02-07 09:13

I have two dictionaries containing a string key and then an object. The object contains five fields. Is there an elegant way to ensure both dictionaries first contain the same k

5条回答
  •  夕颜
    夕颜 (楼主)
    2021-02-07 09:58

    There were a couple of answers on here that I think got pretty close but there were a couple of additional points that I thought should be added so I'm adding them as another possible answer.

    First, I would avoid using the SequenceEquals method. It is an extension method for Enumerable and implicitly requires the two collections to be in the same order. Dictionaries are not meant to be ordered collections so using SequenceEquals means that you'll have to needlessly iterate over both of the dictionaries to create sorted/ordered intermediary collections that you also don't need and then iterate over those collections to compare them for equality. That seems really inefficient and an abuse of LINQ, all in the name of trying to be terse and write a one line solution. If the OP's idea of "elegant" is terse, I guess this will do the trick, but it seems wasteful.

    On the other hand, if the OP's idea of "elegant" is efficient, then you'll probably need to write a little more code. First, you should either override the Equals method for your class or implement IEquatable in your class (see here, for example). This will allow you to compare the values in the dictionary. Then, you'll probably want to do something like implement an interface like IEqualityComparer for your dictionary.

    Then, the comparison of the two dictionaries would go something like below. It's just a quick and dirty "back of the napkin" example so it's not an example of the best way to do it, but it's meant to illustrate a way to iterate only as many times over the dictionary as necessary and quit out as soon as an inequality is found.

    First the required code:

    public class Foo
    {
        //members here...
        public override bool Equals(object obj)
        {
            //implementation here
        }
        //You should probably also override GetHashCode to be thorough,
        //but that's an implementation detail...
    }
    
    //This method could stand on its own or you could change it to make it 
    //part of the implementation of one of the comparison interfaces...
    bool DictionariesEqual(Dictionary x, Dictionary y)
    {
        //If we're comparing the same object, it's obviously equal to itself.
        if(x == y)
        {
            return true;
        }
        //Make sure that we don't have null objects because those are
        //definitely not equal.
        if (x == null || y == null)
        {
            return false;
        }
    
        //Stop processing if at any point the dictionaries aren't equal.
        bool result = false;
    
        //Make sure that the dictionaries have the same count.
        result = x.Count == y.Count;
    
        //If we passed that check, keep going.
        if(result)
        {
            foreach(KeyValuePair xKvp in x)
            {
                //If we don't have a key from one in the other, even though
                //the counts are the same, the dictionaries aren't equal so
                //we can fail out.
                Foo yValue;
                if(!y.TryGetValue(xKvp.Key, out yValue))
                {
                    result = false;
                    break;
                }
                else
                {
                    //Use the override of the Equals method for your object
                    //to see if the value from y is equal to the value from
                    //x.
                    result = xKvp.Value.Equals(yValue);
                    if(!result)
                    {
                        //If they're not equal we can just quit out.
                        break;
                    }
                }
            }
        }
        return result;
    }
    

    Then we'd use it like this:

    Dictionary dict1 = new Dictionary();
    Dictionary dict2 = new Dictionary();
    //Fill the dictionaries here...
    
    //Compare the dictionaries
    bool areDictsEqual = DictionariesEqual(dict1, dict2);
    

    So, it's not the most terse code, but it's also not iterating more than necessary. In my opinion, that's more elegant.

提交回复
热议问题