-1

I need to order an unknown array of keywords by the order they occur in a text string.

// random order of unknown values
$keywords = array( "orange", "green apple", "banana" );

// ordered occurrences
$text = "This is text where the keywords can appear as well like green apple trees.
Then follows text where the keywords are in order and surrounded by unique syntax.

((randomly ordered keywords))
((foo))
((banana))
((orange))
((baz))
((green apple))
((baz))
";

// reorder keywords
// maybe preg_match( "/.+\({2}(".$keywordItem.")\).*/", $text, $matches )
// ...


// Order should be banana, orange, green apple
print_r( $keywords );

The solution may include ´preg_match`, but I don't know where to start.

Martin
  • 2,007
  • 6
  • 28
  • 44

3 Answers3

2
  1. First extract the words from the string (I'm assuming each keyword appears in the text in it's own separate line)

    preg_match_all('/[ \t]*\(\((.*)\)\)[ \t]*/', $text, $matches);`
    
  2. Then you take the produced array and intersect with the keywords

    if (isset($matches[1])) {
      $results = array_intersect($matches[1], $keywords);
    }
    

Here's the complete snippet (php pad):

$keywords = array( "orange", "green apple", "banana" );

$text = "This is text where the keywords can appear as well like green apple trees.
The follows text where the keywords are in order and surrounded by unique syntax.

((randomly ordered keywords))
((foo))
((banana))
((orange))
((baz))
((green apple))
((baz))
";

// extract keywords
$matches = array();
$results = array();
preg_match_all('/[ \t]*\(\((.*)\)\)[ \t]*/', $text, $matches);

// Sort keywords
if (isset($matches[1])) {
  $results = array_intersect($matches[1], $keywords);
}

var_dump($results);
Tivie
  • 18,864
  • 5
  • 58
  • 77
  • Thanks, that's even better than just flipping the array since no huge array and I can control the syntax regex directly with out adding before and removíng afterwards. – Martin Nov 18 '15 at 16:00
0

try something like:

$keywordsPos = array();
//find the pos of the first occurrence of each word 
foreach ($keywords as $keyword) {
  $keywordsPos[$keyword] = strpos($text, $keyword);
}
//sort the keywords by their pos
asort($keywordsPos);
//drop the pos but keep the keywords in order. 
$result = array_values(array_flip($keywordsPos));
Bar-code
  • 277
  • 1
  • 6
  • Thanks, works like a charm! – Martin Nov 18 '15 at 15:22
  • This actually fails if the text contains the keywords in free-text. In the OP case given, the first word to appear should be `**banana**`, but with your code the first word give is green apples ([PHP PAD](http://sandbox.onlinephpfunctions.com/code/75929f3dec99c3e13005246f60fa8bfbe27bcf8c)) – Tivie Nov 18 '15 at 15:30
  • @Tivie: You need to match the unique syntax (double brackets). – Martin Nov 18 '15 at 15:33
  • @Martin O_O I'm not the author of this answer, mine is below – Tivie Nov 18 '15 at 15:34
  • I misunderstood the question but it's not hard to add '(('.$keyword.'))' in strpos function : `$keywordsPos[$keyword] = strpos($text, '(('.$keyword.'))');` – Bar-code Nov 18 '15 at 17:42
-1

You can use 'usort' function:

$keywords = array( "orange", "apple", "banana" );

// ordered occurrences
$text = "This is text where the keywords can appear as well like apple trees.
The follows text where the keywords are in order and surrounded by unique syntax.

((foo))
((banana))
((orange))
((baz))
((apple))
((baz))
";

usort($keywords, function ($a, $b) use($text) {
    $countA = substr_count($text, $a);
    $countB = substr_count($text, $b);
    if($countA == $countB)
        return 0;
    return $countA > $countB ? 1 : -1;
});

var_dump($keywords);

Output:

array(3) {
  [0]=>
  string(6) "orange"
  [1]=>
  string(6) "banana"
  [2]=>
  string(5) "apple"
}