public static function stableSort(array $data, callable $sortFn)
    {
        // Decorate each item by creating an array of [value, index]
        array_walk($data, function (&$v, $k) { $v = [$v, $k]; });
        // Sort by the sort function and use the index as a tie-breaker
        uasort($data, function ($a, $b) use ($sortFn) {
            return $sortFn($a[0], $b[0]) ?: ($a[1] < $b[1] ? -1 : 1);
        });

        // Undecorate each item and return the resulting sorted array
        return array_map(function ($v) { return $v[0]; }, array_values($data));
    }
public static function stableSort(array $data, callable $sortFn)
    {
        
        array_walk($data, function (&$v, $k) { $v = [$v, $k]; });
        
        uasort($data, function ($a, $b) use ($sortFn) {
            return $sortFn($a[0], $b[0]) ?: ($a[1] < $b[1] ? -1 : 1);
        });

        
        return array_map(function ($v) { return $v[0]; }, array_values($data));
    }
public static function stableSort ( array $ data , callable $ sortFn ) { // Decorate each item by creating an array of [value, index] array_walk ( $ data , function ( & $ v , $ k ) { $ v = [ $ v , $ k ] ; } ) ; // Sort by the sort function and use the index as a tie-breaker uasort ( $ data , function ( $ a , $ b ) use ( $ sortFn ) { return $ sortFn ( $ a [ 0 ] , $ b [ 0 ] ) ? : ( $ a [ 1 ] < $ b [ 1 ] ? - 1 : 1 ) ; } ) ; // Undecorate each item and return the resulting sorted array return array_map ( function ( $ v ) { return $ v [ 0 ] ; } , array_values ( $ data ) ) ; }
JMESPath requires a stable sorting algorithm, so here we'll implement
a simple Schwartzian transform that uses array index positions as tie
breakers.

@param array    $data   List or map of data to sort
@param callable $sortFn Callable used to sort values

@return array Returns the sorted array
@link http://en.wikipedia.org/wiki/Schwartzian_transform
JMESPath requires a stable sorting algorithm so here we ll implement a simple Schwartzian transform that uses array index positions as tie breakers .