Home > Software engineering >  Find numbers on a string and order by them
Find numbers on a string and order by them

Time:11-17

I have this string

$s = "red2 blue5 black4 green1 gold3";

I need to order by the number, but can show the numbers. Numbers will always appears at the end of the word. the result should be like:

$s = "green red gold black blue";

Thanks!

CodePudding user response:

Does it always follow this pattern - separated by spaces?

I would break down the problem as such:

  1. I would first start with parsing the string into an array where the key is the number and the value is the word. You can achieve this with a combination of preg_match_all and array_combine

  2. Then you could use ksort in order to sort by the keys we set with the previous step.

  3. Finally, if you wish to return your result as a string, you could implode the resulting array, separating by spaces again.

An example solution could then be:

<?php

$x = "red2 blue5 black4 green1 gold3";

function sortNumberedWords(string $input) {
    preg_match_all('/([a-zA-Z] )([0-9] )/', $input, $splitResults);
    $combined = array_combine($splitResults[2], $splitResults[1]);

    ksort($combined);

    return implode(' ', $combined);
}

echo sortNumberedStrings($x);

The regex I'm using here matches two seperate groups (indicated by the brackets):

  1. The first group is any length of a string of characters a-z (or capitalised). Its worth noting this only works on the latin alphabet; it won't match ö, for example.
  2. The second group matches any length of a string of numbers that appears directly after that string of characters.

The results of these matches are stored in $splitResults, which will be an array of 3 elements:

  1. [0] A combined list of all the matches.
  2. [1] A list of all the matches of group 1.
  3. [2] A list of all the matches of group 2.

We use array_combine to then combine these into a single associative array. We wish for group 2 to act as the 'key' and group 1 to act as the 'value'.

Finally, we sort by the key, and then implode it back into a string.

CodePudding user response:

$s = "red2 blue5 black4 green1 gold3";
$a=[];
preg_replace_callback('/[a-z0-9] /',function($m) use (&$a){
    $a[(int)ltrim($m[0],'a..z')] = rtrim($m[0],'0..9');
},$s);
ksort($a);
print " Version A: ".implode(' ',$a);

$a=[];
foreach(explode(' ',$s) as $m){
    $a[(int)ltrim($m,'a..z')] = rtrim($m,'0..9');
}
ksort($a);
print " Version B: ".implode(' ',$a);

preg_match_all("/([a-z0-9] )/",$s,$m);
foreach($m[1] as $i){
    $a[(int)substr($i,-1,1)] = rtrim($i,'0..9');
}
ksort($a);
print " Version C: ".implode(' ',$a);

Use one of them, but also try to understand whats going on here.

  • Related