考虑到N位哈希(例如md5()的输出),我有2种情况需要解决:
相同的哈希值,应始终在该范围内或从同一输入数组返回相同的数字或数组键。如果输入数组发生变化,但哈希值保持不变,那么我将获得不同的选择。
例如,我会有这样的代码:
echo intFromHash(1, 100, 'abcd'); // 15
echo intFromHash(1, 100, 'defg'); // 90
echo arrayValueFromHash(['moe', 'joe', 'pike'], 'abcd'); // 'joe'
echo arrayValueFromHash(['pike', 'dolly']); // pike
答案 0 :(得分:1)
您可以使用crc32()
PHP函数在1行代码中编写intFromHash()
:
function intFromHash($min, $max, $hash {
return $min + crc32($hash) % ($max - $min + 1);
}
如果您在32位系统上运行abs(crc32($hash))
(请参阅文档以获取详细信息)。
然后,您可以使用它来实现arrayValueFromHash()
(在另一行代码中):
function arrayValueFromHash(array $array, $hash) {
return $array[intFromHash(0, count($array) - 1, $hash)];
}
如果return $array[array_keys($array)[intFromHash(...)]];
是一个关联数组,请使用$array
(如问题中列出的那样,代码中显示的表达式仅适用于数字索引数组。)
答案 1 :(得分:0)
我想出来了。这是任何需要它的人的代码:
/**
* Return a key from an array based on a given 4-bit hash.
*
* @param array $array Array to return a key from.
* @param string $hash 4-bit hash. If hash is longer than 4-bit only first 4 bits will be used.
* @return mixed
*/
function getArrayValueByHash($array, $hash)
{
$arrayKeys = array_keys($array);
$index = getIntFromHash(0, sizeof($arrayKeys)-1, $hash);
return $array[$arrayKeys[$index]];
}
/**
* Return an integer in range, based on a hash.
*
* @param int $start
* @param int $end
* @param string $hash 4-bit hash. If hash is longer than 4-bit only first 4 bits will be used.
* @return int
*/
function getIntFromHash($start, $end, $hash)
{
$size = $end-$start;
$hash = str_split($hash);
$intHash = ord($hash[0]) * 16777216 + ord($hash[1]) * 65536 + ord($hash[2]) * 256 + ord($hash[3]);
$fits = $intHash / $size;
$decimals = $fits - floor($fits);
$index = floor($decimals * $size);
return $start+$index;
}