Afraz Ali
Afraz Ali

Reputation: 2762

How to compare Dictionary values ignoring case

I have two dictionaries and I want to compare them. I want to ignore case and only return false if they have different values. Here is my code.

var dic1 = new Dictionary<String, String>(StringComparer.CurrentCultureIgnoreCase);
            dic1.Add("Key 2", "Value 2");
            dic1.Add("Key 1", "Value 1"); 


            var dic2 = new Dictionary<String, String>(StringComparer.CurrentCultureIgnoreCase);
            dic2.Add("Key 1", "Value 1");
            dic2.Add("Key 2", "Value 2");

            var areEqual = dic1.OrderBy(r => r.Key).SequenceEqual(dic2.OrderBy(r => r.Key));

            Console.WriteLine(areEqual);

As you can see I am using the SequenceEqual method of the dictionary class to compare the two dictionaries. I have ordered them by key so that the result is not false if the key position is different. The problem I cant seem to figure out is how to ignore the case in key and values and return false only if values are different. In my case value 1 and VALUE 1 are both equal and the result should be true. That is not my case here.

Upvotes: 1

Views: 2398

Answers (4)

Andrei V
Andrei V

Reputation: 7508

You should really check if the lengths are equal and if the two dictionaries have the same keys. Once you get past this part, you can use the following snippet:

var dic1 = new Dictionary<String, String>();
dic1.Add("Key 2", "Value 2");
dic1.Add("Key 1", "Value 1");

var dic2 = new Dictionary<String, String>();
dic2.Add("Key 1", "Value 1");
dic2.Add("Key 2", "Value 2");

bool areEqual = dic1.OrderBy(x => x.Key).Select(x => x.Value.ToUpperInvariant())
     .SequenceEqual(dic2.OrderBy(x => x.Key).Select(x => x.Value.ToUpperInvariant()));

Console.WriteLine(areEqual);

Upvotes: 2

Tim Schmelter
Tim Schmelter

Reputation: 460238

Order by the key, select the value and use the overload of SequenceEqual with StringComparer.OrdinalIgnoreCase:

 bool areEqual = dic1.OrderBy(x => x.Key).Select(kv => kv.Value)
  .SequenceEqual(dic2.OrderBy(x => x.Key).Select(kv => kv.Value), StringComparer.OrdinalIgnoreCase);

These enforce a byte-by-byte comparison similar to strcmp that not only avoids bugs from linguistic interpretation of essentially symbolic strings, but provides better performance.

http://msdn.microsoft.com/en-us/library/ms973919.aspx

Upvotes: 2

Afraz Ali
Afraz Ali

Reputation: 2762

Ended up using custom comparer to compare the values. Here is the code.

class Program
    {
        static void Main(string[] args)
        {
            var dic1 = new Dictionary<String, String>();
            dic1.Add("Key 2", "Value 2");
            dic1.Add("Key 1", "Value 1"); 


            var dic2 = new Dictionary<String, String>();
            dic2.Add("Key 1", "Value 1");
            dic2.Add("Key 2", "Value 2");

            var areEqual = dic1.OrderBy(r => r.Key).SequenceEqual(dic2.OrderBy(r => r.Key), new ProductComparer());

            Console.WriteLine(areEqual);

            Console.ReadLine();
        }
    }



    internal class ProductComparer : IEqualityComparer<KeyValuePair<string, string>>
    {
        public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
        {
            Boolean areEqual = (String.Compare(x.Key, y.Key, StringComparison.OrdinalIgnoreCase) == 0) && (String.Compare(x.Value, y.Value, StringComparison.OrdinalIgnoreCase) == 0);
            return areEqual;
        }

        public int GetHashCode(KeyValuePair<string, string> obj)
        {
            return obj.GetHashCode();
        }
    }

Upvotes: 1

ddoor
ddoor

Reputation: 5973

Firstly, check the lengths - if they aren't equal then return false.

Next iterate over each member and compare the values (assuming the have the same order). You can also do this by iterating over the first dictionary and checking to see if each element is in the second dictionary. As soon as it is not, break from the loop or return false.

Upvotes: 0

Related Questions