【问题标题】:Why is value comparison in hashtable returning false even when the values are the same?为什么即使值相同,哈希表中的值比较也会返回 false?
【发布时间】:2015-03-09 02:08:48
【问题描述】:

在下面的代码中,我试图检查两个字符串是否是字谜。为此,我通过将唯一字符存储为键并将其在字符串中的计数存储为值来计算哈希表中两个字符串中的字符。最后,当我去检查每个字符是否具有相同的计数时,我得到一个错误的输出,请参见代码中标记为“问题”的行。但是当我将该行中的值转换为字符串时,代码可以正常工作。我错过了什么?

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

【问题讨论】:

    标签: c# hashtable


    【解决方案1】:

    Hashtable 类不是通用的;它只包含Objects,而不是特定类型。

    当你这样做时:

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

    uniqueChars[key] 的编译时类型是Object,而不是Int32。因此,您正在使用不等式运算符的 Object 实现,它只是比较引用。由于Int32是值类型,并且索引器返回一个对象,所以值是boxed;并且由于您将两个值装箱,因此您会得到两个不同的对象实例,因此引用相等总是返回 false。

    您有多种选择:

    • 使用Dictionary<char, int>,它是Hashtable 的通用等价物
    • 在比较之前将值转换为int

      if ((int)uniqueChars1[key] != (int)uniqueChars2[key])
      
    • 使用Equals 方法比较值:

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

    除非您仍在使用 .NET 1.x,否则我强烈建议您尽可能使用泛型集合。它们更安全、更直观,并且对值类型具有更好的性能。


    旁注(与您的问题无关):您无需通过引用AddToHashTable 来传递Hashtable;如果没有ref 修饰符,代码的工作方式完全相同,因为Hashtable 是一个引用类型,所以无论如何它总是一个被传递的引用。 ref 修饰符仅在您为 uniqueChars 参数分配其他内容时有用,或者如果您正在传递值类型并改变其状态(这通常被认为是一件坏事)。我建议你阅读Jon Skeet's great article about value types, reference types, and parameter passing

    【讨论】:

    • 你的意思是Hashtable 是一个引用类型,对吧?不是方法AddToHashTable
    【解决方案2】:

    您的问题来自!= 将比较两个对象的引用相等性这一事实。 uniqueCharsX[key] 返回一个装在对象内的 int,而您从两个哈希表返回的 int 相同,但它们返回的盒子不是同一个盒子,因此您得到的值不正确。

    要么使用强类型 Dictionary<char, int> 而不是哈希表,要么使用 !uniqueChars1[key].Equals(uniqueChars2[key]) 而不是 uniqueChars1[key] != uniqueChars2[key],这将拆箱 int 并比较值(我强烈建议您使用字典。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 2017-04-08
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 2019-10-03
      相关资源
      最近更新 更多