我在搜索Bloom过滤器时在GitHub上遇到了这个简单的PHP类,这被命名为“Bloom过滤器”,但我认为它更像是一个“哈希表”,不管我好奇,它很简单了解。
它读入一个单词文件并为每个单词创建一个哈希数组键,然后你可以检查这个单词是否存在于哈希数组中。
我很好奇,虽然使用这个有什么好处,只是将实际的单词存储为数组键或值,然后检查数组中是否存在该单词,理论上这只会增加开销并做同样的事情,请帮我理解我错过的东西?
<?php
class Dictionary {
private $words;
private $wordsHash;
public $hashLength;
public function __construct($filepath, $hashLength) {
$this->words = file($filepath);
$this->hashLength = $hashLength;
foreach($this->words as $word){
$this->wordsHash[$this->createHash($word)] = true;
}
echo 'words: ' . count($this->words) . ' hashes: ' . count($this->wordsHash) . "\n";
}
public function createHash($str){
$hash = substr(md5(trim($str)), 0, $this->hashLength);
return $hash;
}
public function checkDictionary($str){
$hash = $this->createHash(trim($str));
if(array_key_exists ($hash , $this->wordsHash)){
return true;
}
return false;
}
}
?>
dictionary.txt文件中有10,000个单词,我将只展示一些演示
der
die
und
in
den
von
zu
das
mit
sich
des
auf
für
ist
使用示例:
<?php
$dictionary = new Dictionary('dictionary.txt', 30);
if($dictionary->checkDictionary('den')){
echo 'The Word den Exist in the Hash Table';
}else{
echo 'The Word den DOES NOT Exist in the Hash Table';
}
?>
答案 0 :(得分:6)
这个想法似乎是搜索密钥要比在数组中搜索特定值快得多。对于非常大的阵列尤其如此。但是,我建议采用一种更简单的方法(如您所说)避免开销和冲突:
$words = array_flip( file($filename) );
// The actual values are now the keys!
// So checking for a word works like this:
if (isset($words['und'])) {
// ...
// Travling through the words works like this:
foreach ($words as $word => $i) {
// ...
(PS:这段代码不会按预期工作,因为每个单词都会包含换行符,所以你需要先删除它。但我希望你明白这一点。)
答案 1 :(得分:3)
这种方法通常使用非常大的字符串来完成。我在创建图库时曾经使用过这种方法。上传的文件将以整个文件的sha1
校验和命名(实际名称保存在数据库中)。这样,如果上传了重复文件,则很容易被拒绝。
我不知道从哈希3个字母字符串(甚至50个字母字符串)中获得什么好处。我不这样做。你会问原始开发者。
答案 2 :(得分:2)
如果您在github上找到它 - 可能值得向作者询问您找到的代码。
字典类确实有两个好处 - 它可以修剪键,避免重复,但下面的代码大致相同,而且速度可能更快:
$words = file($filepath);
$words = array_map('trim', $words);
$words = array_unique($words);
sort($words); // just for convenience debugging
...
if (in_array($test, $words)) {
return true;
} else {
return false;
}
如果有疑问,对每个(或任何)竞争技术进行基准测试应该清楚地表明哪个是给定用例的最佳解决方案。
答案 3 :(得分:2)
我在构造函数之间看到没有功能差异,只是使用单词本身作为键。 php中带有非数字的数组本质上是散列图(在语法和实现中,如果我没记错的话)。请考虑以下代码段:
$contents = file($filepath);
$dictionary = array();
foreach($contents as $word) {
$dictionary[$word] = $word;
}
if(array_key_exists('den', $dictionary){
echo 'The Word den Exist in the Hash Table';
}else{
echo 'The Word den DOES NOT Exist in the Hash Table';
}
它与示例类完全相同。你唯一丢失的是->
语法,但你可以在技术上使用$dictionary['den']
作为你的存在条件......如果没有设置它会返回null,它的计算结果为false,所以...
该课程还提供计算机科学禁止使用不需要加密安全性的cyptographic哈希函数。 MD5算法的运行成本要高于常规的,非安全的(相对来说,调用MD5安全性,这点可疑)哈希函数。除了没有真正提供任何东西之外,使用字典类会明显变慢。正如Truth所指出的,比较非常长的字符串的摘要可以节省您的时间。但计算摘要仍然很昂贵,3个字母字符串的计算摘要只不过是浪费时间。