2012-05-03 122 views
4

我在GitHub上搜索Bloom Filter时遇到了这个简单的PHP类,它被命名为“Bloom Filter”,但我认为它更像是一个“哈希表”,我好奇的是它很容易理解。PHP哈希键阵列

它读入一个单词文件并为每个单词创建一个散列数组键,然后可以检查散列数组中是否存在该单词。

我很好奇,虽然有没有使用这个的任何好处,只是将实际的单词存储为数组键或值,然后检查该单词是否存在于数组中,理论上这只会增加开销并做同样的事情事情,请帮助我了解我失踪了什么?

<?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文件中有10000个字,我将只显示演示几个

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'; 
} 
?> 
+2

在我看来,你可以用普通的PHP数组来做这件事,就像散列一样行事 – hackartist

+1

@hackartist:那就是我在想什么,但我觉得必须有一个理由让人经历了这个麻烦? – JasonDavis

回答

5

与此有关的想法似乎是,搜索关键是比搜索数组中的特定值快得多。对于非常大的数组尤其如此。不过,我会建议一个更简单的方法(因为你已经说的)开销避免和碰撞:

$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:因为每一个字如预期将包括换行符此代码将无法工作,所以你需要但我希望你能明白这一点)

3

这种方法一般是用做非常大的字符串。创建图库时,我曾经使用过这种方法。上传的文件将以整个文件的sha1校验和命名(而实际名称保存在数据库中)。这样,如果重复上传文件,它将很容易被拒绝。

我不确定从散列3个字母字符串(甚至是50个字母字符串)获得的好处。我不会那样做。你会问最初的开发者。

2

如果你在github上找到它 - 可能值得问你找到的代码的作者。

字典类并有2个好处 - 它修剪键,并避免重复,但下面的代码大多是等价的,可能是快了很多:

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

如有疑问,标杆每个(或任何)竞争技术应明确指出哪一个是给定用例的最佳解决方案。

2

我在该构造函数和仅使用单词本身作为关键字之间没有功能差异。用非数字的php数组基本上是hashmaps(在语法和实现中,如果我没有记错的话)。请考虑以下代码片段:

$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,所以...

该类还提供计算机科学禁止使用密码安全性不需要的密码散列函数。 MD5算法比常规的非安全(相对而言;相对而言;调用MD5安全性在这一点上是可疑的)散列函数运行起来要昂贵得多。除了没有真正提供任何东西外,使用字典类会显着变慢。正如真相指出的那样,比较非常长的字符串的摘要可以节省您的时间。但计算摘要仍然很昂贵,计算3个字母字符串的摘要不过是浪费时间。