Why does comparing values ​​in a hash table return false even when the values ​​are the same?

In the following code, I am trying to check if two strings are anagrams. To this I count the characters in two lines in a hash table, storing the unique characters as the key and my score in the string as values. At the end, when I go to check if each of the characters has the same count, I get a false output, see the line labeled "PROBLEM" in the code. But when I convert the values ​​in this string to a string, the code works fine. What am I missing?

    static bool AreAnagrams(string input1, string input2)
    {
        Hashtable uniqueChars1 = new Hashtable();
        Hashtable uniqueChars2 = new Hashtable();

        // Go through first string and create a hash table of characters 
        AddToHashTable(input1, ref uniqueChars1);
        // Go through second string and create a second hash table of characters
        AddToHashTable(input2, ref uniqueChars2);

        // For each unique character, if the count from both hash tables are the same, they are anagrams
        if (uniqueChars1.Keys.Count != uniqueChars2.Keys.Count)
        {
            return false;
        }
        else
        {
            foreach (object key in uniqueChars1.Keys)
            {
                if (uniqueChars1[key] != uniqueChars2[key]) // ***PROBLEM HERE***
                {
                    return false;
                }
            }
        }
        return true;
    }

    static void AddToHashTable(string input, ref Hashtable uniqueChars)
    {
        foreach (char c in input)
        {

            if (!uniqueChars.ContainsKey(c))
            {
                uniqueChars.Add(c, 1);
            }
            else
            {
                int charCount = Convert.ToInt32(uniqueChars[c]);
                charCount++;
                uniqueChars[c] = charCount;
            }
        }
    }

      

+3


source to share


2 answers


The class is Hashtable

not shared; it just contains Object

s, not a specific type.

When you do this:

if (uniqueChars1[key] != uniqueChars2[key])

      

compile time type uniqueChars[key]

is equal Object

, not Int32

. So you are using an implementation of Object

the inequality operator, which simply compares references. Since Int32

is a value type and the indexer returns an object, the value is in the box ; and since you are boxing two values, you get two different object instances, so referential equality always returns false.

You have several options:



  • use Dictionary<char, int>

    which is the general equivalentHashtable

  • pass values int

    before comparison:

    if ((int)uniqueChars1[key] != (int)uniqueChars2[key])
    
          

  • use method Equals

    to compare values:

    if (!uniqueChars1[key].Equals(uniqueChars2[key]))
    
          

If you are still using .NET 1.x, I highly recommend that you use shared collections wherever you can. They are safer, more intuitive, and have better performance for value types.


Side note (not related to your problem): you don't need to pass Hashtable

by link AddToHashTable

; the code will work exactly the same without the modifier ref

because it Hashtable

is a reference type, so it is always a reference that is passed anyway. The modifier ref

would only be useful if you were assigning something else to a parameter uniqueChars

, or if you were passing a value type and changing its state (which is usually considered bad). I suggest you read Jon Skeet's excellent article on value types, reference types, and parameter passing .

+5


source


Your problem has to do with what !=

will be comparing reference equality on two objects. uniqueCharsX[key]

returns an int placed inside an object, while you have the same int returning from both hash tables, the field they return to is not the same field, so you get the wrong value.



Either use strongly typed Dictionary<char, int>

instead of a hash table, or use !uniqueChars1[key].Equals(uniqueChars2[key])

instead uniqueChars1[key] != uniqueChars2[key]

that will uninstall int and compare its value (I highly recommend you use a dictionary.)

+1


source







All Articles