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;
}
}
}
source to share
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 .
source to share
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.)
source to share