Search code examples
phparrayssortingstable-sort

How to stable-sort a flat array by each string's trailing integer


$array = array(
   'list1 - 1',
   'list7 - 1',
   'list5 - 2',
   'list3 - 1'
);

I need sort to this array numerically. The function should check the value after the equal sign for sorting.


result:
list1 - 1
list7 - 1
list3 - 1
list5 - 2

In the above result, the order is not changed either alphabetically or numerically until `list[5]`. How do I do this?

Solution

  • It looks like you want to search firstly on the trailing numbers, but if they are the same then you want to retain the original order of the items. This means a little more thinking is necessary but the job is, in essence, still very simple.

    $array = array(
       'list1 - 1',
       'list7 - 1',
       'list5 - 2',
       'list3 - 1',
    );
    
    function sort_list(&$subject) {
        // Get an array of the trailing numbers to use within the callback
        $nums = preg_replace('/^.* - (\d+)$/', '$1', $subject);
        // Sort values by trailing number or key
        uksort($subject, function($a,$b) use ($nums) {
            // If numbers are the same, sort by key
            if ($nums[$a] === $nums[$b]) {
                return $a - $b;
            }
            // Othwerise sort by numbers
            return $nums[$a] - $nums[$b];
        });
    }
    
    sort_list($array);
    var_dump($array);
    

    Outputs something like:

    array(4) {
      [0]=>
      string(9) "list1 - 1"
      [1]=>
      string(9) "list7 - 1"
      [3]=>
      string(9) "list3 - 1"
      [2]=>
      string(9) "list5 - 2"
    }