2010-02-17 18 views
4

我要找無論是常規或方法來尋找錯誤容忍字符串比較。PHP - 聰明,錯誤容忍字符串比較

比方說,我們有測試字符串Čakánka - 是的,它包含CE字符。

現在,我不想接受任何以下字符串作爲OK

  • cakanka
  • cákanká
  • ČaKaNKA
  • CAKANKA
  • CAAKNKA
  • CKAANKA
  • cakakNa

的問題是,我經常開關在字中的字母,我想用不能夠最大限度地減少用戶的挫折(即你很忙)寫一個字的權利。

所以,我知道如何使CI比較(只是使它小寫:]),我可以刪除CE人物,我只是不能換我的頭周圍容忍少數切換字符。

另外,你經常把一個人物不僅在錯誤的地方(character =>cahracter),但有時由多個地方(character =>carahcter)編寫過程中轉移,只是因爲一個手指是懶惰。

謝謝:]

回答

4

不知道(尤其是對重音/特殊字符的東西,你可能要應對第一),但對於那些在錯誤的地方或丟失字符,則levenshtein功能,計算Levenshtein distance兩個字符串之間,可以幫助你(引用)

int levenshtein (string $str1 , string $str2 ) 
int levenshtein (string $str1 , string $str2 , int $cost_ins , int $cost_rep , int $cost_del ) 

的Levenshtein距離定義爲 最小數目的字符,你 必須更換,插入或刪除,以 轉化成STR1 STR2


其他可能有用的功能可能是soundexsimilar_text,或metaphone

有的就這些功能的手冊頁,用戶音符尤其是manual page of levenshtein可能會帶給你一些有用的東西太多;-)

+0

口音都沒有問題,我會做的第一件事就是'uppercase'的字符串,然後替換的重音字符與非重音版本('ž'=>'z') –

+0

我只是可能檢查你,其中一個功能將是有益的,我100%確定。 –

+0

出於好奇,當你說「其中一個功能」時,你究竟在考慮哪一個? levenshtein之一,還是另一個? –

1

拼寫檢查功能,這樣做fuzzy string comparison。也許你可以根據這個參考來調整算法。或者從像Firefox這樣的開源項目中獲取拼寫檢查器猜測代碼。

+0

謝謝,但@Pascal MARTIN指着我更好的方向發展:] –

3

你可以音譯詞拉丁字符和使用語音算法像Soundex從你的單詞中獲得本質並將它與你所擁有的相比較。在你的情況下,除了最後一個是C250之外,你的所有單詞都是C252


編輯與像levenshteinsimilar_text比較功能的問題是,需要調用它們的每對輸入值和可能的匹配值的。這意味着如果你有一個有100萬條記錄的數據庫,你將需要調用這些函數100萬次。

但功能soundexmetaphone,計算某種摘要,可以幫助減少實際比較的數量。如果存儲數據庫中每個已知單詞的soundexmetaphone值,則可以非常快地減少可能的匹配數。之後,當可能的匹配值的集合減少時,則可以使用比較函數來獲得最佳匹配。

下面是一個例子:

// building the index that represents your database 
$knownWords = array('Čakánka', 'Cakaka'); 
$index = array(); 
foreach ($knownWords as $key => $word) { 
    $code = soundex(iconv('utf-8', 'us-ascii//TRANSLIT', $word)); 
    if (!isset($index[$code])) { 
     $index[$code] = array(); 
    } 
    $index[$code][] = $key; 
} 

// test words 
$testWords = array('cakanka', 'cákanká', 'ČaKaNKA', 'CAKANKA', 'CAAKNKA', 'CKAANKA', 'cakakNa'); 
echo '<ul>'; 
foreach ($testWords as $word) { 
    $code = soundex(iconv('utf-8', 'us-ascii//TRANSLIT', $word)); 
    if (isset($index[$code])) { 
     echo '<li> '.$word.' is similar to: '; 
     $matches = array(); 
     foreach ($index[$code] as $key) { 
      similar_text(strtolower($word), strtolower($knownWords[$key]), $percentage); 
      $matches[$knownWords[$key]] = $percentage; 
     } 
     arsort($matches); 
     echo '<ul>'; 
     foreach ($matches as $match => $percentage) { 
      echo '<li>'.$match.' ('.$percentage.'%)</li>'; 
     } 
     echo '</ul></li>'; 
    } else { 
     echo '<li>no match found for '.$word.'</li>'; 
    } 
} 
echo '</ul>'; 
+0

這非常有趣,但可能對我的需求太模糊。謝謝你。 –