PHP search array with multiple keywords and sorted result

I have a plan to do a search from the txt file that I am preparing, the contents of the txt file are similar to this below

a.txt

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

If the code was like that,

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

The result will be only Emma Jefferson

Then if I use this code

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

The result will be like this:

 Amy Jefferson Emma West Donna Jefferson Emma Watson Emma Jefferson 

The only result, but Emma Jefferson in the last result

So the question is, how can I look for Emma Jefferson, the result was like this.

 Emma Jefferson Emma Watson Emma West Amy Jefferson Donna Jefferson 

So, basically he searches for the word "Emma Jefferson" first, and then "Emma", and the last - "Jefferson"

UPDATE I vote for "Not a panic code for this problem," but I want to thank you for all the participants here. Do not panic, RomanPerekhrest, Sui Dream, Jere, i-man, all of you are the best!

Pattygeek

+5
source share
5 answers

I don’t know how to take the position of matches using a regular expression solution, but if you convert the search string and terms into arrays of words, this can be done.

With this approach, we iterate over text elements and create an array of match positions for each word in search terms, then sort the result by the number of matches, then by the position of the matches.

 $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); 
+1
source

You are currently echoing the results immediately, so they are ordered as they are in the text.

You can search for full string and partial matches, and then concatenate the 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>"; 

Update:

A few words option:

 $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
source

Complete solution:

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

Output:

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

You will need to write a new loop or start sorting your Array time intervals, because the foreach-loop takes one element name at a time, checks to see if it matches your search word, and if so, the name goes at the end of your new $matches[] array $matches[] . In this way,

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

the part knows nothing about names that are already or are inside $matches[] .

So my suggestion would be:

 $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
source

I would use the preg_match_all solution:

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

You can also give the file as a string and avoid the implode part.

0
source

Source: https://habr.com/ru/post/1272052/


All Articles