Php 使用Levenshtein距离重新排列单词

Php 使用Levenshtein距离重新排列单词,php,fuzzy-logic,fuzzywuzzy,Php,Fuzzy Logic,Fuzzywuzzy,摘要 我试图找到php中的名称匹配百分比,但在此之前,我需要根据第一个字符串重新排列字符串中的单词 源代码是关于什么的? 我有两条线。首先,我将两个字符串都添加到数组中,如果字符串中有空格,则将其添加到数组中。 $arraydataBaseName和$arraybankData来自我的第一个数组,即$arraydataBaseName我正在搜索$arraybankData的所有值并获取密钥。我得到了正确的键排列,但无法将其特定位置的值排列到新数组中 $dataBaseName = "Jardin

摘要

我试图找到php中的名称匹配百分比,但在此之前,我需要根据第一个字符串重新排列字符串中的单词

源代码是关于什么的?

我有两条线。首先,我将两个字符串都添加到数组中,如果字符串中有空格,则将其添加到数组中。 $arraydataBaseName和$arraybankData来自我的第一个数组,即$arraydataBaseName我正在搜索$arraybankData的所有值并获取密钥。我得到了正确的键排列,但无法将其特定位置的值排列到新数组中

$dataBaseName = "Jardine Lloyd Thompson";
$bankdata = "Thompson Thompson Jardine"; 

$replacedataBaseName = preg_replace("#[\s]+#", " ", $dataBaseName);
$replacebankData = preg_replace("#[\s]+#", " ", $bankdata); 

$arraydataBaseName = explode(" ",$replacedataBaseName);
$arraybankData = explode(" ",$replacebankData); 

echo "<br/>";
print_r($arraydataBaseName);

$a="";
$i="";
$arraysize =  count($arraydataBaseName);

$push=array();
for($i=0;$i< $arraysize;$i++)
{     
  if(array_search($arraybankData[$i],$arraydataBaseName)>0)
  {
    ${"$a$i"} =  array_search($arraybankData[$i],$arraydataBaseName); 
    //echo ${"$a$i"};
    array_push($push,${"$a$i"});
   }    
 }
 print_r($push); 
$dataBaseName=“怡和劳埃德汤普森”;
$bankdata=“汤普森-汤普森怡和”;
$replacedataBaseName=preg#u replace(“#[\s]+#“,”,$dataBaseName);
$replacebankData=preg#u replace(“#[\s]+#”,”,$bankdata);
$arraydataBaseName=explode(“,$replacedataBaseName);
$arraybankData=explode(“,$replacebankData”);
回声“
”; 打印(arraydataBaseName); $a=“”; $i=“”; $arraysize=count($arraydataBaseName); $push=array(); 对于($i=0;$i<$arraysize;$i++) { 如果(数组搜索($arraybankData[$i],$arraydataBaseName)>0) { ${“$a$i”}=array_搜索($arraybankData[$i],$arraydataBaseName); //echo${“$a$i”}; 数组_push($push,${“$a$i”}); } } 打印(推送);
案例1: 输入

数据库名称=怡和劳埃德汤普森

银行名称=汤普森怡和劳埃德

输出

预期输出=怡和劳埃德汤普森

案例2:## 输入

数据库名称=怡和劳埃德汤普森

银行名称=Thoapson Jordine Llayd

如果在上述数据库名称中找不到单词,则预期的搜索将基于leventish算法单词,该算法的距离将被视为关键字

输出

预期输出=Jordine Llayd Thoapson

问题更新
当用户输入的
$bankdata
包含更多无法匹配的单词时,我需要将这些单词附加到末尾。

我已在案例1和案例2中分解了代码。
但是很明显,如果var_导出为false,则使用相同的变量执行案例2代码

//Case 1:
$DatabaseName = "Jardine Lloyd Thompson";
$BankName = "Thompson Jardine Lloyd";

//Split and sort them
$data = explode(" ", $DatabaseName);
$bank = explode(" ", $BankName);
sort($data);
sort($bank);
Var_export(($data == $bank)); //true

//Case 2
$DatabaseName = "Jardine Lloyd Thompson";
$BankName = "Thoapson Jordine Llayd";

//Split and sort
$data = explode(" ", $DatabaseName);
$bank = explode(" ", $BankName);
sort($data);
sort($bank);

// Loop and accumulate the levenshtein return
$lev = 0;
foreach($data as $key => $name){
    $lev += levenshtein($name, $bank[$key]);
}

echo PHP_EOL . $lev; // 3 letters "off"

同一代码中情况1和2的示例

$DatabaseName = "Jardine Lloyd Thompson";
$BankName = "Thoapson Jordine Llayd";

$data = explode(" ", $DatabaseName);
$bank = explode(" ", $BankName);
sort($data);
sort($bank);
if($data == $bank){
    echo "true";
    exit;
    // No need to do levenshtein
}

$lev = 0;
foreach($data as $key => $name){
    $lev += levenshtein($name, $bank[$key]);
}

echo PHP_EOL . $lev;

这是一个简单的版本,随后逐字查找最佳匹配

declare (strict_types=1);

$dataBaseName = 'Jardine Lloyd Thompson';

$bankdataRows =
[
  'Thompson Jardine Lloyd',
  'Blaaa  Llayd Thoapson   f***ing user input   Jordine   aso. ',
];

// assume the "database" is already stored trimmed since it is server-side controlled
$dbWords = preg_split("#[\s]+#", $dataBaseName);

foreach ($bankdataRows as $bankdata)
{
  // here we trim the data received from client-side.
  $bankWords = preg_split("#[\s]+#", trim($bankdata));
  $result    = [];

  if(!empty($bankWords))
    foreach ($dbWords as $dbWord)
    {
      $idx   = null;
      $least = PHP_INT_MAX;

      foreach ($bankWords as $k => $bankWord)
        if (($lv = levenshtein($bankWord, $dbWord)) < $least)
        {
          $least = $lv;
          $idx   = $k;
        }

      $result[] = $bankWords[$idx];
      unset($bankWords[$idx]);
    }

  $result = array_merge($result, $bankWords);
  var_dump($result);
}


您可能希望扩展此方法,首先计算每个可能组合的Levenshtein距离,然后选择最佳的整个匹配。

@Quasimodo's One我通过比较$bankdata和$DatabaseName成功地获得了单词的位置!有真正的数据库吗?@casimodo'sclone没有,这只是你读过的变量名?@casimodo'sclone是的,我能很容易地找到距离。安排单词是我感到困惑的一步谢谢你分享我与你的解决方案太接近了,但是当我通过$dataBaseName=trim('jardinemarks llord thompson')$bankdataRows=[$dataBaseName,trim('lloyd thodal jardine');我得到的输出是正确的,但有错误提示:未定义的偏移量:0,对于本例,$dataBaseName=trim('jardine llord thompson')$bankdataRows=[$dataBaseName,trim('lloyd thodal jardine spark');当第二个变量有4个单词时,如果1个单词不匹配,则应将其附加在末尾或空白处。请建议我已尝试,但面临一些问题issue@daoootim只需附加剩余的银行字
$result=array\u merge($result,$bankWords)
为了保留剩余部分的顺序,我已将排序转换为一个
foreach
循环。@daoootim如果问题中没有描述更多问题,请根据SO政策针对一个特定问题提出一个新问题。@Quasimodo的克隆传奇谢谢您,当我尝试此名称数据库name='E SRINIVAS'和BankName='SRINIVAS ETTAMALLA'ExpectedOutput='ETTAMALLA SRINIVAS'时需要您的帮助,我将获得此输出='SRINIVAS ETTAMALLA'@Andreas谢谢您回答,但在找到levenshtein后需要重新排列单词,例如:DatabaseName='e SRINIVAS'和BankName='SRINIVAS ETTAMALLA'ExpectedOutput='ETTAMALLA SRINIVAS'
array(3) {
  [0] =>
  string(7) "Jardine"
  [1] =>
  string(5) "Lloyd"
  [2] =>
  string(8) "Thompson"
}

array(8) {
  [0] =>
  string(7) "Jordine"
  [1] =>
  string(5) "Llayd"
  [2] =>
  string(8) "Thoapson"
  [3] =>
  string(5) "Blaaa"
  [4] =>
  string(7) "f***ing"
  [5] =>
  string(4) "user"
  [6] =>
  string(5) "input"
  [7] =>
  string(4) "aso."
}