Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Search Array With Multiple Keywords And Sorted Result

Tags:

php

I have a plan to make search from txt file that I prepare, the txt file content similar like 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 this

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

Unique result, but "Emma Jefferson" in the last result

So the question is how I can search Emma Jefferson, the result sort was like this

Emma Jefferson
Emma Watson
Emma West
Amy Jefferson
Donna Jefferson

So basically it search for "Emma Jefferson" entire word first, then "Emma" and the last one is "Jefferson"

UPDATE I vote for Don't Panic code for this problem, but i wanna say thank you for all contributor here Don't Panic, RomanPerekhrest, Sui Dream, Jere, i-man, all of you are the best!!

Pattygeek

like image 880
pattygeek Avatar asked Nov 08 '22 16:11

pattygeek


1 Answers

I don't know of a way to take the position of the matches into account with a regex solution, but if you convert the search string and the terms to arrays of words, it can be done.

With this approach, we iterate the text items and build an array of position matches for each word in the search term, then sort the result by number of matches, then position of 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);
like image 87
Don't Panic Avatar answered Nov 15 '22 07:11

Don't Panic