为任何PHP值生成整数哈希代码

为任何PHP值生成整数哈希代码,php,hash,hashcode,Php,Hash,Hashcode,我正在寻找一种方法,在PHP中,为任何值基元类型或用户定义类(类似trie的结构)生成整数哈希代码。此哈希应具有以下属性: 对于对象$x和$y,其中$x===y,hashCode($x)==hashCode($y) 返回一个32位的值 理想情况下,散列函数应分布均匀(即不会有太多冲突) 尽可能快(无需编写C扩展名) 我能想到的最好方法是获取字符串哈希并将其转换为整数: <?php function hashCode($o) { // Get a string hash for t

我正在寻找一种方法,在PHP中,为任何值基元类型或用户定义类(类似trie的结构)生成整数哈希代码。此哈希应具有以下属性:

  • 对于对象
    $x
    $y
    ,其中
    $x===y
    hashCode($x)==hashCode($y)
  • 返回一个32位的值
  • 理想情况下,散列函数应分布均匀(即不会有太多冲突)
  • 尽可能快(无需编写C扩展名)
  • 我能想到的最好方法是获取字符串哈希并将其转换为整数:

    <?php
    
    function hashCode($o) {
        // Get a string hash for the value
        if( is_object($o) ) {
            // For objects, use spl_object_hash
            $strHash = spl_object_hash($o);
        }
        else {
            // Now we know we have a primitive type
    
            // For arrays, first hash the contents
            if( is_array($o) )
                $o = array_map(function($x) { return hashCode($x); }, $o);
    
            // Use serialisation to get a string for the primitive
            // NOTE: We could use casting to a string since, however this will
            //       lead to more collisions since, for instance,
            //       (string)true === '1'
            //       Also, casting a float to a string causes it to lose precision,
            //       meaning more collisions
            //       Maybe this is OK though...
            // We use md5 to reduce the size (think serialising a large string)
            $strHash = md5(serialize($o));
        }
    
        // Convert the string hash to a 32-bit integer
        return crc32($strHash);
    }
    

    这是我能找到的所有哈希选项

    适用于字符串,但也可以转换为数组/对象

    /**
     * Make a control key with the string containing datas
     *
     * @param  string $data        Data
     * @param  string $controlType Type of control 'md5', 'crc32' or 'strlen'
     * @throws Zend_Cache_Exception
     * @return string Control key
     */
    protected function _hash($data, $controlType)
    {
        switch ($controlType) {
        case 'md5':
            return md5($data);
        case 'crc32':
            return crc32($data);
        case 'strlen':
            return strlen($data);
        case 'adler32':
            return hash('adler32', $data);
        default:
            Zend_Cache::throwException("Incorrect hash function : $controlType");
        }
    }
    

    如果您不介意我问的话,用例是什么?与数组相比,您处理对象的方式可能存在冲突。对象哈希是从运行时的唯一对象id创建的。为数组创建一个数组必须从其值派生。换句话说,两个相同的数组将具有相同的散列,而一个对象的两个克隆则不会。@SverriM.Olsen-我正在尝试为不可变映射实现一个散列数组映射trie(这更多是出于好奇,而不是出于任何有用的目的,但如果它可能有用就好了…!@Flosculus-我知道这一点,这就是我们想要的行为。一个对象的两个克隆也会在
    ==
    测试中失败,所以我很高兴它们的哈希值会有所不同