Lanz
Lanz

Reputation: 115

PHP additional parameters to usort

The following code lays within a function which itself lays within a class. Its purpose is to avoid having one sorting function per $filter value :

$GLOBAL['filter'] = $filter;
usort($this->data, function($arr1, $arr2) {
    return ($arr1[$GLOBALS['filter']] > $arr2[$GLOBALS['filter']]) ? 1 : -1;
});

My solution works perfectly fine, but I find it rather inelegant. Would somebody have an idea to acheive the same goal without resorting to the $GLOBALS variable ?

Thanks for your propositions

Upvotes: 7

Views: 5135

Answers (3)

mickmackusa
mickmackusa

Reputation: 47992

In modern PHP, there are better tools available.

From PHP7, the spaceship operator (<=>) is available to make a 3-way comparison. This is more reliable than a "greater than / less than" 2-way comparison.

From PHP7.4, arrow functions allow more concise syntax and remove the need for use().

Code:

usort($this->data, fn($arr1, $arr2) => $arr1[$filter] <=> $arr2[$filter]);

If value in $filter might not exist as a key in the arrays, then you can use ?? (null coalescing operator) to fallback to a default value.

usort(
    $this->data,
    fn($arr1, $arr2) => ($arr1[$filter] ?? $fallback) <=> ($arr2[$filter] ?? $fallback)
);

Upvotes: 0

Himanshu Joshi
Himanshu Joshi

Reputation: 39

   public function sortList($params, $listToSort)
    {
        if (!isset($listToSort) || !isset($params) || count($params) == 0) {
            return $listToSort;
        }
        foreach ($params as $col => $value) {
            $orderFlag = $value == 'asc' ? 1 : -1;
            usort($listToSort, function ($a, $b) use ($orderFlag, $col) {
                return strcmp($a[$col], $b[$col]) * $orderFlag;
            });
        }
    return $listToSort;
}

Above $params is json eg: {name : 'asc', age : 'desc'} and $listToSort is array of array eg: array(array('name': 'Himanshu', age: 22), array('name': 'Steve', age: 35))

Place this code in Utils.php of your project as it is a general solution.

Upvotes: 0

Matteo Riva
Matteo Riva

Reputation: 25060

Since you're using an anonymous function, you can use it as a closure like this:

$filter = <whatever>;
usort($this->data, function($arr1, $arr2) use ($filter) {
    return ($arr1[$filter] > $arr2[$filter]) ? 1 : -1;
});

Upvotes: 26

Related Questions