phparrayssortingsubstringnatural-sort

Naturally sort the leading and trailing parts of undelimited strings in a flat array


I have this array:

$array = array('E1211', 'E2172', 'E2181', 'E233', 'E241', 'E286');

I need to order first by first number-letter, i.e. E1, E2, E3, E4... followed by ordered numbers from lowest to highest.

Desired order would be: E1211, E233, E241, E286, E2172, E2181


If I do sort($array);, the order will incorrectly be: "E1211", "E2172", "E2181", "E233", "E241" "E286".

If I do natsort($array);, it will incorrectly order by numbers from lowest to highest: "E233", "E241", "E286", "E1211", "E2172", "E2181"


Solution

  • Use usort() with a custom comparison function to split the strings and compare the portions.

    <?php
    
    $array = array('E1211','E2172','E2181','E233','E241','E286');
    
    usort($array, function($a, $b){
        $pfxA = substr($a,0,2);  // Get the first two characters of each string
        $pfxB = substr($b,0,2);
        if ( $pfxA !== $pfxB) {return $pfxA<=>$pfxB;}  // If they're not equal, return the spaceship comparison
        
        return (int)substr($a,2)<=>(int)substr($b,2);  // Prefixes are equal. Convert the rest to integers and return the spaceship comparison.
    });
    
    
    var_dump($array);
    

    Output:

    array(6) {
      [0]=>
      string(5) "E1211"
      [1]=>
      string(4) "E233"
      [2]=>
      string(4) "E241"
      [3]=>
      string(4) "E286"
      [4]=>
      string(5) "E2172"
      [5]=>
      string(5) "E2181"
    }
    

    See https://3v4l.org/5qts5