NSDictionary中的哈希值(Hash value of NSDictionary)

2019-07-31 00:38发布

我遇到了一个问题,在这里我得到了不同的字典相同的哈希值。 也许我做得不对明显,但我认为,与不同的内容(也就是不相等的对象)的对象应该有不同的哈希值。

NSDictionary *dictA = @{ @"foo" : @YES };
NSDictionary *dictB = @{ @"foo" : @NO };

BOOL equal = [dictA hash] == [dictB hash];

NSAssert(!equal, @"Assuming, that different dictionaries have different hash values.");

有什么想法吗?

Answer 1:

有没有保证两个不同的对象会有不同的哈希值。

在最新的CoreFoundation的开源版本 ,一个CFDictionary(其等同于一个NSDictionary)的散列被定义为:

static CFHashCode __CFDictionaryHash(CFTypeRef cf) {
    return __CFBasicHashHash((CFBasicHashRef)cf);
}

__CFBasicHashHash被定义为 :

__private_extern__ CFHashCode __CFBasicHashHash(CFTypeRef cf) {
    CFBasicHashRef ht = (CFBasicHashRef)cf;
    return CFBasicHashGetCount(ht);
}

这是简单的存储在集合中的条目数。 在换言之,两个[dictA hash][dictB hash]的散列值是1,在词典中的条目数。

虽然这是一个非常糟糕的哈希算法,CF没做什么错在这里。 如果你需要有一个更准确的哈希值,你可以在一个OBJ-C类自己提供一个。



Answer 2:

与仅整数字典,字符串等我会用dict.description.hash作为一个快速的代码。



Answer 3:

基于A解决方案伊戈尔- kulagin的回答是不依赖于顺序:

@implementation NSDictionary (Extensions)

- (NSUInteger) hash
{
    NSUInteger prime = 31;
    NSUInteger result = 1;
    for (NSObject *key in [[self allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
        result = prime * result + [key hash];
        result = prime * result + [self[key] hash];
    }
    return result;
}
@end

然而,仍然有冲突的可能性,如果字典包含其他字典作为值。



Answer 4:

函数“哈希”不是一个真正的散列函数。 它提供了不同的值的字符串(所有可预见的),但集合(数组和字典),它只是返回计数。 如果你想要一个独特的哈希值,你可以自己使用的素数,或功能srandom()和随机()计算,或探索CommonCrypto / CommonDigest.h提供一个真正的散列函数一样SHA1



Answer 5:

我创建的NSDictionary类别,并在此基础上回答重写哈希方法: 对的isEqual覆盖的最佳做法:和hash

@implementation NSDictionary (Extensions)

- (NSUInteger) hash {
    NSUInteger prime = 31;
    NSUInteger result = 1;

    NSArray *sortedKeys = [self.allKeys sortedArrayUsingSelector: @selector(compare:)];
    for (NSObject *key in sortedKeys) {
        result = prime * result + key.hash;
        id value = self[key];
        if ([value conformsToProtocol: @protocol(NSObject)] == YES) {
            result = prime * result + [value hash];
        }
    }

    return result;
}

@end

和迅速实施。

extension Dictionary where Key: Comparable, Value: Hashable {
    public var hashValue: Int {
        let prime = 31
        var result = 1

        let sortedKeys = self.keys.sorted()
        for (key) in sortedKeys {
            let value = self[key]!
            result = Int.addWithOverflow(Int.multiplyWithOverflow(prime, result).0, key.hashValue).0
            result = Int.addWithOverflow(Int.multiplyWithOverflow(prime, result).0, value.hashValue).0
        }

        return result
    }
}

完美这也需要实现Equatable的协议Dictionary ,所以你也可以添加Hashable协议一致性。



文章来源: Hash value of NSDictionary