2017-09-22 96 views
5

我有一个计划,以使从txt文件的搜索,我准备,类似这样的txt文件内容如下PHP搜索数组多个关键字和排序结果

A.TXT

Amy Jefferson 
Nathalie Johnson 
Emma West 
Donna Jefferson 
Tanya Nathalie 
George West 
Emma Watson 
Emma Jefferson 

如果代码是这样

a.php只会

$filename = "a.txt"; 
$example = file($filename, FILE_IGNORE_NEW_LINES); 
$searchword = 'Emma Jefferson'; 
$matches = array(); 
foreach($example as $k=>$v) { 
    if(preg_match("/\b$searchword\b/i", $v)) { 
     $matches[$k] = $v; 
     echo $matches[$k]."<br>"; 
    } 
} 

结果只会 “艾玛·杰斐逊”

然后,如果我使用此代码

b.php

$filename = "a.txt"; 
$example = file($filename, FILE_IGNORE_NEW_LINES); 
$searchword = 'Emma Jefferson'; 
$matches = array(); 
foreach($example as $k=>$v) { 
    $searchword2 = str_ireplace(" ", "|", $searchword); 
    if(preg_match("/\b$searchword2\b/i", $v)) { 
     $matches[$k] = $v; 
     echo $matches[$k]."<br>"; 
    } 
} 

结果会是这样

Amy Jefferson 
Emma West 
Donna Jefferson 
Emma Watson 
Emma Jefferson 

独特的结果,但 “艾玛·杰斐逊” 在最后的结果

所以问题是我如何搜索艾玛杰斐逊,结果排序是这样的

Emma Jefferson 
Emma Watson 
Emma West 
Amy Jefferson 
Donna Jefferson 

所以基本上是搜索“艾玛·杰斐逊”整个单词,然后再“艾玛”,最后一个是“杰斐逊”

UPDATE 我投做这个惊慌代码问题,但我想说在这里感谢你的所有贡献者不要惊慌,RomanPerekhrest,隋梦,杰尔,我的人,你们都是最棒的!

Pattygeek

回答

1

我不知道的方式来采取比赛的位置考虑用正则表达式解决方案,但如果转换搜索字符串和条款可以完成单词数组。

使用这种方法,我们迭代文本项目并为搜索词中的每个单词构建一个位置匹配数组,然后按结果匹配数和匹配位置对结果进行排序。

$search_words = explode(' ', strtolower($searchword)); 

foreach ($example as $item) { 
    $item_words = explode(' ', strtolower($item)); 

    // look for each word in the search term 
    foreach ($search_words as $i => $word) { 
     if (in_array($word, $item_words)) { 

      // add the index of the word in the search term to the result 
      // this way, words appearing earlier in the search term get higher priority 
      $result[$item][] = $i; 
     } 
    } 
} 

// this will sort alphabetically if the uasort callback returns 0 (equal) 
ksort($result); 

// sort by number of matches, then position of matches  
uasort($result, function($a, $b) { 
    return count($b) - count($a) ?: $a <=> $b; 
}); 

// convert keys to values  
$result = array_keys($result); 
+0

嗨不要恐慌,谢谢你的回应:)但我仍然得到那种不像我想要的,这就是我得到的艾玛杰佛逊艾玛沃森唐娜杰佛逊艾玛西艾米杰弗逊,同时我想就在列表上的结果我上面写过 – pattygeek

+0

啊,我明白了,所以这不仅仅是比赛的数量,还是比赛的顺序呢? –

+0

是的:D那部分有点让我困惑:D – pattygeek

0

您当前回显结果,所以它们按照文本排序。

您可以搜索完整的字符串和部分匹配,然后concatenate results

foreach($example as $k=>$v) { 
    if(preg_match("/\b$searchword\b/i", $v)) { 
     $fullMatches[] = $v; 
    } 
    if(preg_match("/\b$searchword2\b/i", $v)) { 
     $matches[] = $v; 
    } 
} 
$matches = array_unique(array_merge($fullMatches, $matches)); 
foreach($matches as $k => $v) 
    echo $v . "<br>"; 

更新:

多个词的变体:

$words = ['Emma', 'Jefferson']; 
$matches = array(); 
foreach($example as $k => $v) { 
    $fullStr = implode(' ', $words); 
    if(preg_match("/\b$fullStr\b/i", $v)) 
     $matches[0][] = $v; 
    $str = ""; 
    $i = 1; 
    foreach($words as $word) { 
     if ($str === "") 
      $str = $word; 
     else 
      $str .= '|' . $word; 
     if(preg_match("/\b$str\b/i", $v)) 
      $matches[$i][] = $v; 
     $i++; 
    } 
} 
$result = array(); 
foreach($matches as $firstKey => $arr) { 
    foreach($arr as $secondKey => $v) { 
     $result[] = $v; 
    } 
} 
$result = array_unique($result); 
foreach($result as $k => $v) 
    echo $v . "<br>"; 
+0

感谢隋因为我想要的回应:),其艾玛 - 杰弗森在上面工作,但其余的还是不喜欢,代码的结果你把它给我的是这样的 艾玛·杰斐逊 艾米杰斐逊 艾玛西 唐娜·杰斐逊 艾玛·沃特森 同时,结果,我想这样的一个 艾玛·杰斐逊 艾玛·沃特森 艾玛西 艾米杰斐逊 唐娜·杰斐逊 – pattygeek

+0

是否有可能使它的动态,我的意思是搜索可以是任何字不仅2 – pattygeek

+0

对不起隋,但为什么当我尝试你的代码时,a.txt上的所有数据都显示? – pattygeek

0

络合物溶液:

$lines = file('a.txt', FILE_IGNORE_NEW_LINES); 
$name = 'Emma'; 
$surname = 'Jefferson'; 
$emmas = $jeffersons = []; 

foreach ($lines as $l) { 
    if (strpos($l, $name) === 0) { 
     $emmas[] = $l; 
    } elseif (strrpos($l, $surname) === (strlen($l) - strlen($surname))) { 
     $jeffersons[] = $l; 
    } 
} 

usort($emmas, function($a,$b){ 
    return strcmp(explode(' ', $a)[1], explode(' ', $b)[1]); 
}); 
usort($jeffersons, function($a,$b){ 
    return strcmp($a, $b); 
}); 

$result = array_merge($emmas, $jeffersons); 
print_r($result); 

输出:

Array 
(
    [0] => Emma Jefferson 
    [1] => Emma Watson 
    [2] => Emma West 
    [3] => Amy Jefferson 
    [4] => Donna Jefferson 
) 
+0

嗨Roman,谢谢你的回应:)结果就像我想要的,但问题是,是否有可能使$ name和$ surname是动态的,因为在这里搜索可以超过2个单词 – pattygeek

+0

@pattygeek,如果*搜索可以超过2个单词* - 你将如何排序4或更多单词分开吗?这对你来说将是非常困难的情况。我的解决方案解决了当前问题 – RomanPerekhrest

0

你将不得不编写一个新的循环或开始排序你的数组后缀,因为foreach循环在当时接受一个元素名称,测试它是否与你的搜索词相匹配,如果它符合,名字在末尾您的新阵列$matches[]。所以

if(preg_match("/\b$searchword2\b/i", $v)) { 
    $matches[$k] = $v; 
    echo $matches[$k]."<br>"; 
} 

部分不知道是或不是已经是$matches[]里面的名字什么。

所以我的建议是:

$filename = "a.txt"; 
$example = file($filename, FILE_IGNORE_NEW_LINES); 
$searchword = 'Emma Jefferson'; 
$matches = array(); 



$searchword2 = array($searchword, explode(" ", $searchword)[0], explode(" ", $searchword)[1]); 
$isThisNameAlreadyInTheList; 

foreach($searchword2 as $actualSearchword) { 

    foreach($example as $k=>$v) { 

     $isThisNameAlreadyInTheList = false; 
     foreach($matches as $match) { 
      if(preg_match("/\b$match\b/i", $v)) { 
       $isThisNameAlreadyInTheList = true; 
      } 
     } 

     if (!$isThisNameAlreadyInTheList) { 
      if(preg_match("/\b$actualSearchword\b/i", $v)) { 
       $matches[$k] = $v; 
       echo $matches[$k]."<br>"; 
      } 
     } 
    } 

} 
+0

感谢Jere对这部分的回应:) $ searchword2 = array(“Emma Jefferson”,“Emma”,“Jefferson”);它可以使动态,我尝试$ searchword2 = explode(“|”,$ searchword);但仍然混淆在哪里把“艾玛杰斐逊” – pattygeek

+0

这是我上传代码时犯的一个错误。它现在应该是正确的。 – Jere

+0

对不起,迟到了,Jere的工作!但如果结果如何超过2个字?可以在不编辑$ searchword2的情况下进行搜索? – pattygeek

0

我会用一个preg_match_all的解决方案,像这样:

$searchName = "Emma Jefferson"; 
$searchTerms = explode(' ', $searchName); 

$pattern = "/(\b$searchTerms[0]\b \b$searchTerms[1]\b)|(\b$searchTerms[0]\b \w+)|(\w* \b$searchTerms[1]\b)/i"; 

$output = []; 
preg_match_all($pattern, implode(' | ', $example), $out); 

foreach($out as $k => $o){ 
    if($k == 0){ 
     continue; 
    } 

    foreach($o as $item){ 
     if(!empty($item)){ 
      $output[] = $item; 
     } 
    } 
} 

print_r($output); 

你也可以将文件作为一个字符串,避免了内爆部分。

+0

嗨我的人感谢回应:)结果就像我想要的一样!但模式部分,我如何使它动态?谢谢 – pattygeek

+0

我更新了我的答案,使搜索字词在名称之间的空格更加动态分割 –

+0

对不起,对于迟到的回复,i-man如果搜索超过2个单词怎么办?它还在工作吗? – pattygeek