usort

(PHP 4, PHP 5, PHP 7, PHP 8)

usort使用用户自定义的比较函数对数组中的值进行排序

说明

usort(array &$array, callable $callback): true

根据用户提供的比较函数,对 array 原地排序。

注意:

如果两个成员完全相同,那么它们将保持原来的顺序。 在 PHP 8.0.0 之前,它们在排序数组中的相对顺序是未定义的。

注意: 此函数为 array 中的元素赋与新的键名。这将删除原有的键名,而不是仅仅将键名重新排序。

参数

array

输入的数组

callback

在第一个参数小于,等于或大于第二个参数时,该比较函数必须相应地返回一个小于,等于或大于 0 的整数。

callback(mixed $a, mixed $b): int
警告

从比较函数中返回非整数值,例如 float,将导致内部强制转换为 callback 返回值为 int。因此,诸如 0.990.1 之类的值都将被转换为整数值 0,将这些值比较的话将会是相等。

返回值

总是返回 true

更新日志

版本 说明
8.2.0 现在返回类型为 true;之前是 bool
8.0.0 如果 callback 接受引用传递参数,该方法将会抛出 E_WARNING

示例

示例 #1 usort() 示例

<?php
function cmp($a, $b)
{
if (
$a == $b) {
return
0;
}
return (
$a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

foreach (
$a as $key => $value) {
echo
"$key: $value\n";
}
?>

以上示例会输出:

0: 1
1: 2
2: 3
3: 5
4: 6

注意:

很明显在这个小例子中用 sort() 函数更合适。

示例 #2 使用多维数组的 usort() 示例

<?php
function cmp($a, $b)
{
return
strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits, "cmp");

foreach (
$fruits as $key => $value) {
echo
"\$fruits[$key]: " . $value["fruit"] . "\n";
}
?>

当排序多维数组时,$a$b 包含到数组第一个索引的引用。

以上示例会输出:

$fruits[0]: apples
$fruits[1]: grapes
$fruits[2]: lemons

示例 #3 使用一个对象的成员函数的 usort() 示例

<?php
class TestObj {
private
string $name;

function
__construct($name)
{
$this->name = $name;
}

/* This is the static comparing function: */
static function cmp_obj($a, $b)
{
return
strtolower($a->name) <=> strtolower($b->name);
}
}

$a[] = new TestObj("c");
$a[] = new TestObj("b");
$a[] = new TestObj("d");

usort($a, [TestObj::class, "cmp_obj"]);

foreach (
$a as $item) {
echo
$item->name . "\n";
}
?>

以上示例会输出:

b
c
d

示例 #4 usort() 示例,使用闭包对多维数组进行排序

<?php
$array
[0] = array('key_a' => 'z', 'key_b' => 'c');
$array[1] = array('key_a' => 'x', 'key_b' => 'b');
$array[2] = array('key_a' => 'y', 'key_b' => 'a');

function
build_sorter($key) {
return function (
$a, $b) use ($key) {
return
strnatcmp($a[$key], $b[$key]);
};
}

usort($array, build_sorter('key_b'));

foreach (
$array as $item) {
echo
$item['key_a'] . ', ' . $item['key_b'] . "\n";
}
?>

以上示例会输出:

y, a
x, b
z, c

示例 #5 使用太空船运算符的 usort() 示例

太空船运算符允许跨多个轴直接比较复合值。 下面的示例将对 $people 按姓氏排序,如果姓氏匹配,则按名字排序。

<?php
$people
[0] = ['first' => 'Adam', 'last' => 'West'];
$people[1] = ['first' => 'Alec', 'last' => 'Baldwin'];
$people[2] = ['first' => 'Adam', 'last' => 'Baldwin'];

function
sorter(array $a, array $b) {
return [
$a['last'], $a['first']] <=> [$b['last'], $b['first']];
}

usort($people, 'sorter');

foreach (
$people as $person) {
print
$person['last'] . ', ' . $person['first'] . PHP_EOL;
}
?>

以上示例会输出:

Baldwin, Adam
Baldwin, Alec
West, Adam

参见

add a note add a note

User Contributed Notes 41 notes

up
116
grzeniufication at gmail dot com
7 years ago
Just wanted to show off the beauty of PHPs spaceship operator in this use case.

<?php // tested on PHP 7.1
$a = [2, 1, 3, 6, 5, 4, 7];
$asc = $desc = $a;
usort($asc, function (int $a, int $b) { return ($a <=> $b); });
usort($desc, function (int $a, int $b) { return -($a <=> $b); });
print_r([ $a, $asc, $desc ]);

/**
* Getting ahead of myself but... If arrow function syntax was possible:
* usort($asc, (int $a, int $b) => ($a <=> $b));
* usort($desc, (int $a, int $b) => -($a <=> $b));
*/
?>
up
118
zuallauz at gmail dot com
11 years ago
When trying to do some custom sorting with objects and an anonymous function it wasn't entirely clear how this usort function works. I think it probably uses a quicksort in the background. Basically it actually moves the $b variable up or down in respect to the $a variable. It does NOT move the $a variable inside the callback function. This is key to getting your logic right in the comparisons.

If you return -1 that moves the $b variable down the array, return 1 moves $b up the array and return 0 keeps $b in the same place.

To test I cut down my code to sorting a simple array from highest priority to lowest.

<?php
$priorities
= array(5, 8, 3, 7, 3);

usort($priorities, function($a, $b)
{
    if (
$a == $b)
    {
        echo
"a ($a) is same priority as b ($b), keeping the same\n";
        return
0;
    }
    else if (
$a > $b)
    {
        echo
"a ($a) is higher priority than b ($b), moving b down array\n";
        return -
1;
    }
    else {
        echo
"b ($b) is higher priority than a ($a), moving b up array\n";               
        return
1;
    }
});

echo
"Sorted priorities:\n";
var_dump($priorities);
?>

Output:

b (8) is higher priority than a (3), moving b up array
b (5) is higher priority than a (3), moving b up array
b (7) is higher priority than a (3), moving b up array
a (3) is same priority as b (3), keeping the same
a (8) is higher priority than b (3), moving b down array
b (8) is higher priority than a (7), moving b up array
b (8) is higher priority than a (5), moving b up array
b (8) is higher priority than a (3), moving b up array
a (5) is higher priority than b (3), moving b down array
a (7) is higher priority than b (5), moving b down array

Sorted priorities:
array(5) {
  [0]=> int(8)
  [1]=> int(7)
  [2]=> int(5)
  [3]=> int(3)
  [4]=> int(3)
}
up
6
user dot boba at gmail dot com
6 years ago
PHP7 spaceship operator very helpful in sorting function callback

http://php.net/manual/en/migration70.new-features.php#migration70.new-features.spaceship-op

<?php

// PHP < 7 example
function cmp($a, $b)
{
    if (
$a == $b) {
        return
0;
    }
    return (
$a < $b) ? -1 : 1;
}

// PHP7 example
function cmp($a, $b)
{
    return
$a <=> $b;
}
up
20
Gok6tm
12 years ago
this is a new multisort function for sorting on multiple subfield like it will be in sql : 'ORDER BY field1, field2'
number of sort field is undefined
<?php

$array
[] = array('soc' => 3, 'code'=>1);
$array[] = array('soc' => 2, 'code'=>1);
$array[] = array('soc' => 1, 'code'=>1);
$array[] = array('soc' => 1, 'code'=>1);
$array[] = array('soc' => 2, 'code'=>5);
$array[] = array('soc' => 1, 'code'=>2);
$array[] = array('soc' => 3, 'code'=>2);

//usage
print_r(multiSort($array, 'soc', 'code'));

function
multiSort() {
   
//get args of the function
   
$args = func_get_args();
   
$c = count($args);
    if (
$c < 2) {
        return
false;
    }
   
//get the array to sort
   
$array = array_splice($args, 0, 1);
   
$array = $array[0];
   
//sort with an anoymous function using args
   
usort($array, function($a, $b) use($args) {

       
$i = 0;
       
$c = count($args);
       
$cmp = 0;
        while(
$cmp == 0 && $i < $c)
        {
           
$cmp = strcmp($a[ $args[ $i ] ], $b[ $args[ $i ] ]);
           
$i++;
        }

        return
$cmp;

    });

    return
$array;

}
?>

output:
Array
(
    [0] => Array
        (
            [soc] => 1
            [code] => 1
        )

    [1] => Array
        (
            [soc] => 1
            [code] => 1
        )

    [2] => Array
        (
            [soc] => 1
            [code] => 2
        )

    [3] => Array
        (
            [soc] => 2
            [code] => 1
        )

    [4] => Array
        (
            [soc] => 2
            [code] => 5
        )

    [5] => Array
        (
            [soc] => 3
            [code] => 1
        )

    [6] => Array
        (
            [soc] => 3
            [code] => 2
        )

)
up
22
Nsisodia91 at gmail dot com
8 years ago
You can also sort multi-dimensional array for multiple values like as

<?php
$arr
= [
    [
       
"name"=> "Sally",
       
"nick_name"=> "sal",
       
"availability"=> "0",
       
"is_fav"=> "0"
   
],
    [
       
"name"=> "David",
       
"nick_name"=> "dav07",
       
"availability"=> "0",
       
"is_fav"=> "1"
   
],
    [
       
"name"=> "Zen",
       
"nick_name"=> "zen",
       
"availability"=> "1",
       
"is_fav"=> "0"
   
],
    [
       
"name"=> "Jackson",
       
"nick_name"=> "jack",
       
"availability"=> "1",
       
"is_fav"=> "1"
   
],
    [
       
"name"=> "Rohit",
       
"nick_name"=> "rod",
       
"availability"=> "0",
       
"is_fav"=> "0"
   
],

];

usort($arr,function($a,$b){
   
$c = $b['is_fav'] - $a['is_fav'];
   
$c .= $b['availability'] - $a['availability'];
   
$c .= strcmp($a['nick_name'],$b['nick_name']);
    return
$c;
});

print_r($arr);
?>

Output:

Array
(
    [0] => Array
        (
            [name] => Jackson
            [nick_name] => jack
            [availability] => 1
            [is_fav] => 1
        )

    [1] => Array
        (
            [name] => David
            [nick_name] => dav07
            [availability] => 0
            [is_fav] => 1
        )

    [2] => Array
        (
            [name] => Zen
            [nick_name] => zen
            [availability] => 1
            [is_fav] => 0
        )

    [3] => Array
        (
            [name] => Rohit
            [nick_name] => rod
            [availability] => 0
            [is_fav] => 0
        )

    [4] => Array
        (
            [name] => Sally
            [nick_name] => sal
            [availability] => 0
            [is_fav] => 0
        )

)
up
21
gmail.com - nmcquay
14 years ago
I wrote a wrapper for usort that lets you use something similar to an SQL ORDER BY clause. It can sort arrays of associative arrays and arrays of objects and I think it would work with some hybrid case.

Example of how the function works:

<?php
$testAry
= array(
  array(
'a' => 1, 'b' => 2, 'c' => 3),
  array(
'a' => 2, 'b' => 1, 'c' => 3),
  array(
'a' => 3, 'b' => 2, 'c' => 1),
  array(
'a' => 1, 'b' => 3, 'c' => 2),
  array(
'a' => 2, 'b' => 3, 'c' => 1),
  array(
'a' => 3, 'b' => 1, 'c' => 2)
);

Utility::orderBy($testAry, 'a ASC, b DESC');

//Result:
$testAry = array(
  array(
'a' => 1, 'b' => 3, 'c' => 2),
  array(
'a' => 1, 'b' => 2, 'c' => 3),
  array(
'a' => 2, 'b' => 3, 'c' => 1),
  array(
'a' => 2, 'b' => 1, 'c' => 3),
  array(
'a' => 3, 'b' => 2, 'c' => 1),
  array(
'a' => 3, 'b' => 1, 'c' => 2)
);
?>

To sort an array of objects you would do something like:
Utility::orderBy($objectAry, 'getCreationDate() DESC, getSubOrder() ASC');

This would sort an array of objects that have methods getCreationDate() and getSubOrder().

Here is the function:

<?php
class Utility {
   
/*
    * @param array $ary the array we want to sort
    * @param string $clause a string specifying how to sort the array similar to SQL ORDER BY clause
    * @param bool $ascending that default sorts fall back to when no direction is specified
    * @return null
    */
   
public static function orderBy(&$ary, $clause, $ascending = true) {
       
$clause = str_ireplace('order by', '', $clause);
       
$clause = preg_replace('/\s+/', ' ', $clause);
       
$keys = explode(',', $clause);
       
$dirMap = array('desc' => 1, 'asc' => -1);
       
$def = $ascending ? -1 : 1;

       
$keyAry = array();
       
$dirAry = array();
        foreach(
$keys as $key) {
           
$key = explode(' ', trim($key));
           
$keyAry[] = trim($key[0]);
            if(isset(
$key[1])) {
               
$dir = strtolower(trim($key[1]));
               
$dirAry[] = $dirMap[$dir] ? $dirMap[$dir] : $def;
            } else {
               
$dirAry[] = $def;
            }
        }

       
$fnBody = '';
        for(
$i = count($keyAry) - 1; $i >= 0; $i--) {
           
$k = $keyAry[$i];
           
$t = $dirAry[$i];
           
$f = -1 * $t;
           
$aStr = '$a[\''.$k.'\']';
           
$bStr = '$b[\''.$k.'\']';
            if(
strpos($k, '(') !== false) {
               
$aStr = '$a->'.$k;
               
$bStr = '$b->'.$k;
            }

            if(
$fnBody == '') {
               
$fnBody .= "if({$aStr} == {$bStr}) { return 0; }\n";
               
$fnBody .= "return ({$aStr} < {$bStr}) ? {$t} : {$f};\n";               
            } else {
               
$fnBody = "if({$aStr} == {$bStr}) {\n" . $fnBody;
               
$fnBody .= "}\n";
               
$fnBody .= "return ({$aStr} < {$bStr}) ? {$t} : {$f};\n";
            }
        }

        if(
$fnBody) {
           
$sortFn = create_function('$a,$b', $fnBody);
           
usort($ary, $sortFn);       
        }
    }
}
?>
up
15
sreid at sea-to-sky dot net
20 years ago
As the manual says, "If two members compare as equal, their order in the sorted array is undefined." This means that the sort used is not "stable" and may change the order of elements that compare equal.

Sometimes you really do need a stable sort. For example, if you sort a list by one field, then sort it again by another field, but don't want to lose the ordering from the previous field. In that case it is better to use usort with a comparison function that takes both fields into account, but if you can't do that then use the function below. It is a merge sort, which is guaranteed O(n*log(n)) complexity, which means it stays reasonably fast even when you use larger lists (unlike bubblesort and insertion sort, which are O(n^2)).

<?php
function mergesort(&$array, $cmp_function = 'strcmp') {
   
// Arrays of size < 2 require no action.
   
if (count($array) < 2) return;
   
// Split the array in half
   
$halfway = count($array) / 2;
   
$array1 = array_slice($array, 0, $halfway);
   
$array2 = array_slice($array, $halfway);
   
// Recurse to sort the two halves
   
mergesort($array1, $cmp_function);
   
mergesort($array2, $cmp_function);
   
// If all of $array1 is <= all of $array2, just append them.
   
if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
       
$array = array_merge($array1, $array2);
        return;
    }
   
// Merge the two sorted arrays into a single sorted array
   
$array = array();
   
$ptr1 = $ptr2 = 0;
    while (
$ptr1 < count($array1) && $ptr2 < count($array2)) {
        if (
call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
           
$array[] = $array1[$ptr1++];
        }
        else {
           
$array[] = $array2[$ptr2++];
        }
    }
   
// Merge the remainder
   
while ($ptr1 < count($array1)) $array[] = $array1[$ptr1++];
    while (
$ptr2 < count($array2)) $array[] = $array2[$ptr2++];
    return;
}
?>
up
6
Will Shaver
14 years ago
An even better implementation of osort [than my original, posted on 24-AUG-09 (since deleted)], allowing for multiple properties and directions.  With php 5.3.0 sorting by properties of an object becomes MUCH simpler.  Note that this uses anonymous functions / closures. Might find reviewing the php docs on that useful.  Look below for examples for previous version of php.

<?php
function osort(&$array, $props)
{
    if(!
is_array($props))
       
$props = array($props => true);
       
   
usort($array, function($a, $b) use ($props) {
        foreach(
$props as $prop => $ascending)
        {
            if(
$a->$prop != $b->$prop)
            {
                if(
$ascending)
                    return
$a->$prop > $b->$prop ? 1 : -1;
                else
                    return
$b->$prop > $a->$prop ? 1 : -1;
            }
        }
        return -
1; //if all props equal       
   
});   
}
?>

Usage:

<?php
osort
($items, array("Color" => true, "Size" => false));
//or
osort($items, "Color");
?>
up
6
stephen in koto
17 years ago
For using usort inside a method in an object, where the callback sort method is in the same object, this works:

<?php usort($arr_to_sort, array($this, "sort_terms_by_criteria")); ?>

If you wish to keep elements in their original or reverse order if they are the same length, just don't return zero for items that compare the same. Return a 1 or -1, as appropriate.
up
8
dmhouse at gmail dot com
18 years ago
The easiest way to compare two integers is just to take the second away from the first. For example, say you wanted to sort by an integer property of an object. Your comparison function would look like this:

<?php
function compare_counts($a, $b) {
  return
$a->count - $b->count;
}
?>

This works because you don't necessarily have to return -1, 0 or 1, the manual states any integer less than, equal to or greater than 0 is OK.
up
5
Gerald Schneider
10 years ago
usort returns null when the sorting function is not (yet) defined. The function has to be defined before usort is called, afterwards doesn't work.
up
12
121616591 at qq dot com
6 years ago
You can also sort multi-dimensional array for multiple values like as
<?php
$arr
= array(
    array(
'id'=>1, 'age'=>1, 'sex'=>6, 'name'=>'a'),
    array(
'id'=>2, 'age'=>3, 'sex'=>1, 'name'=>'c'),
    array(
'id'=>3, 'age'=>3, 'sex'=>1, 'name'=>'b'),
    array(
'id'=>4, 'age'=>2, 'sex'=>1, 'name'=>'d'),
);

print_r(arrayOrderBy($arr, 'age asc,sex asc,name desc'));

function
arrayOrderBy(array &$arr, $order = null) {
    if (
is_null($order)) {
        return
$arr;
    }
   
$orders = explode(',', $order);
   
usort($arr, function($a, $b) use($orders) {
       
$result = array();
        foreach (
$orders as $value) {
            list(
$field, $sort) = array_map('trim', explode(' ', trim($value)));
            if (!(isset(
$a[$field]) && isset($b[$field]))) {
                continue;
            }
            if (
strcasecmp($sort, 'desc') === 0) {
               
$tmp = $a;
               
$a = $b;
               
$b = $tmp;
            }
            if (
is_numeric($a[$field]) && is_numeric($b[$field]) ) {
               
$result[] = $a[$field] - $b[$field];
            } else {
               
$result[] = strcmp($a[$field], $b[$field]);
            }
        }
        return
implode('', $result);
    });
    return
$arr;
}
?>

output:
Array
(
    [0] => Array
        (
            [id] => 1
            [age] => 1
            [sex] => 6
            [name] => a
        )

    [1] => Array
        (
            [id] => 4
            [age] => 2
            [sex] => 1
            [name] => d
        )

    [2] => Array
        (
            [id] => 2
            [age] => 3
            [sex] => 1
            [name] => c
        )

    [3] => Array
        (
            [id] => 3
            [age] => 3
            [sex] => 1
            [name] => b
        )

)
up
6
Sid_M
16 years ago
The sample function for having the sort function be a class method has a comment identifying the sorting function as static, however the function does not have the static keyword. In PHP 5 (at least as configured on my server), usort will fail, identifying the method as non-static. Preceding the function keyword with the static keyword fixed the problem.
up
4
xaguilars at gmail dot com
13 years ago
I'd like to share with the community my function for sorting an array of arrays or objects containing associative data. This could be used, for example, with a MySQL result.

<?php
function sort_by($field, &$arr, $sorting=SORT_ASC, $case_insensitive=true){
    if(
is_array($arr) && (count($arr)>0) && ( ( is_array($arr[0]) && isset($arr[0][$field]) ) || ( is_object($arr[0]) && isset($arr[0]->$field) ) ) ){
        if(
$case_insensitive==true) $strcmp_fn = "strnatcasecmp";
        else
$strcmp_fn = "strnatcmp";

        if(
$sorting==SORT_ASC){
           
$fn = create_function('$a,$b', '
                if(is_object($a) && is_object($b)){
                    return '
.$strcmp_fn.'($a->'.$field.', $b->'.$field.');
                }else if(is_array($a) && is_array($b)){
                    return '
.$strcmp_fn.'($a["'.$field.'"], $b["'.$field.'"]);
                }else return 0;
            '
);
        }else{
           
$fn = create_function('$a,$b', '
                if(is_object($a) && is_object($b)){
                    return '
.$strcmp_fn.'($b->'.$field.', $a->'.$field.');
                }else if(is_array($a) && is_array($b)){
                    return '
.$strcmp_fn.'($b["'.$field.'"], $a["'.$field.'"]);
                }else return 0;
            '
);
        }
       
usort($arr, $fn);
        return
true;
    }else{
        return
false;
    }
}
?>
up
2
bob at thecaverlys dot net
9 years ago
Below is a variation on Example #4 that implements a multi-key natural sort on an associative array and can be called in such a way as to allow reversing the sort order and/or making the comparison case insensitive on a key by key basis.

Test code is included in the file – run it from the command line with: php sortUtils.php

<?php
/**
*    sortUtils.php
*/

/**
*    mknatsort() - Multi-Key Natural Sort for associative arrays
*
*    Uses the usort() function to perform a natural sort on a multi-dimensional
*    array on multiple keys. Optionally specifying the sort order for each key
*    and/or ignoring the case for each key value.
*
*    @param array $data_array The array to be sorted.
*    @param mixed $keys The list of keys to be sorted by. This may be a single
*        key or an array of keys
*    @param boolean $reverse Specify whether or not to reverse the sort order. If
*        there are multiple keys then $reverse may be an array of booleans - one
*        per key.
*    @param boolean $ignorecase Specify whether or not to ignore the case when
*        comparing key values.reverse the sort order. If there are multiple keys
*        then $ignorecase may be an array of booleans - one per key.
*/
function mknatsort ( &$data_array, $keys, $reverse=false, $ignorecase=false ) {
   
// make sure $keys is an array
   
if (!is_array($keys)) $keys = array($keys);
   
usort($data_array, sortcompare($keys, $reverse, $ignorecase) );
}

function
sortcompare($keys, $reverse=false, $ignorecase=false) {
    return function (
$a, $b) use ($keys, $reverse, $ignorecase) {
       
$cnt=0;
       
// check each key in the order specified
       
foreach ( $keys as $key ) {
           
// check the value for ignorecase and do natural compare accordingly
           
$ignore = is_array($ignorecase) ? $ignorecase[$cnt] : $ignorecase;
           
$result = $ignore ? strnatcasecmp ($a[$key], $b[$key]) : strnatcmp($a[$key], $b[$key]);
           
// check the value for reverse and reverse the sort order accordingly
           
$revcmp = is_array($reverse) ? $reverse[$cnt] : $reverse;
           
$result = $revcmp ? ($result * -1) : $result;
           
// the first key that results in a non-zero comparison determines
            // the order of the elements
           
if ( $result != 0 ) break;
           
$cnt++;
        }
        return
$result;
    };
}
// end sortcompare()

// test code that will be skipped if this is included in the web environment
// test with: php sortUtils.php from the command line
$sapi_type = php_sapi_name();
if (
substr($sapi_type, 0, 3) == 'cli') {

   
// the following shows several examples of usage and the resulting output.
   
$test[] = array('Status'=>'In Progress', 'comment'=>'This looks good.', 'user_name'=>'John Doe', 'date_modified'=>'06/13/2014 11:20 AM', 'role'=>'Senior Account Manager');
   
$test[] = array('Status'=>'In Progress', 'comment'=>'This looks good, please approve.', 'user_name'=>'John Doe', 'date_modified'=>'06/13/2014 11:19 AM', 'role'=>'Account Manager');
   
$test[] = array('Status'=>'In Progress', 'comment'=>'This looks good.', 'user_name'=>'Jane Smith', 'date_modified'=>'06/13/2014 11:19 AM', 'role'=>'Senior Account Manager');
   
$test[] = array('Status'=>'Returned', 'comment'=>'There is not enough informartion.  Please add the following.', 'user_name'=>'John Doe', 'date_modified'=>'06/13/2014 11:15 AM', 'role'=>'Account Manager');
   
$test[] = array('Status'=>'In Progress', 'comment'=>'I am currently reviewing this.', 'user_name'=>'John Doe', 'date_modified'=>'06/13/2014 11:14 AM', 'role'=>'Account Manager');
    echo
"Original array: ";
   
print_r($test);

    echo
"Sorted on date_modified: ";
   
mknatsort($test, array('date_modified') );
   
print_r($test);

    echo
"Sorted on role(reversed) & date_modified: ";
   
mknatsort($test, array('role','date_modified'),array(true,false) );
   
print_r($test);

    echo
"Sorted on role & date_modified(reversed): ";
   
mknatsort($test, array('role','date_modified'),array(false,true) );
   
print_r($test);
}

?>
up
4
luke dot semerau at gmail dot com
14 years ago
If you need to use usort with a key in the calling method, I wrote this as a utility:
<?php

function usort_comparison($obj, $method, $key) {
   
$usorter = &new Usort($obj, $method, $key);
    return array(
$usorter, "sort");
}

class
Usort {
    function
__construct($obj, $method, $key) {
       
$this->obj = $obj;
       
$this->method = $method;
       
$this->key = $key;
    }
    function
sort($a, $b) {
        return
call_user_func_array(array($this->obj, $this->method), array($a, $b, $this->key));
    }
}

?>

<?php

require_once("util/usort.php");

class
Foo {
   
$items = array(FooBar(13), FooBar(2));
    public function
sorter() {
       
usort($this-items, usort_comparison("Foo", "_cmp", "item"));
    }

    public static function
_cmp($a, $b, $key) {
         return
strcasecmp($a->$key, $b->$key);
    }

}

class
FooBar {
    public
$item;
    function
__construct($val) {
       
$this->item = $val;
    }
}

?>

~ simple example... but in the way I need to use it was the key was used in a switch statement to choose the different member of the object to compare against dynamically (as in, sort by x or y or z)
up
9
josh at wintelcom dot net
22 years ago
This lets you sort an associative multi-dimensional array by multiple key/field names.  Much similiar to the SQL clause ORDER BY.  Enjoy.

<?php
function cmp ($a, $b) {

   
// Populate this array with your values...
    // Below is the SQL equivalent of
    // select * from blah ORDER BY date desc, type asc, name asc

   
$vals = array(
       
'date' => 'd',
       
'type' => 'a',
       
'name' => 'a'
   
);

    while(list(
$key, $val) = each($vals)) {

        if(
$val == "d") {
            if (
$a["$key"] > $b["$key"]) {
                return -
1;
            }
            if (
$a["$key"] < $b["$key"]) {
                return
1;
            }
        }

        if(
$val == "a") {
            if (
$a["$key"] < $b["$key"]) {
                return -
1;
            }
            if(
$a["$key"] > $b["$key"]) {
                return
1;
            }
        }

    }

}
?>
up
4
Raveler at telenet dot be
19 years ago
The array_alternate_multisort function written by robert below doesn't work. There are several bugs in the code and it doesn't work when sorting by multiple keys because the order of the first key isn't taken into account when sorting by the second key and so on. Also, because robert uses strcasecmp the algorithm doesn't work properly with floats or other variable types. Here's the improved version:

<?php
   
function SortArray() {
       
$arguments = func_get_args();
       
$array = $arguments[0];
       
$code = '';
        for (
$c = 1; $c < count($arguments); $c += 2) {
            if (
in_array($arguments[$c + 1], array("ASC", "DESC"))) {
               
$code .= 'if ($a["'.$arguments[$c].'"] != $b["'.$arguments[$c].'"]) {';
                if (
$arguments[$c + 1] == "ASC") {
                   
$code .= 'return ($a["'.$arguments[$c].'"] < $b["'.$arguments[$c].'"] ? -1 : 1); }';
                }
                else {
                   
$code .= 'return ($a["'.$arguments[$c].'"] < $b["'.$arguments[$c].'"] ? 1 : -1); }';
                }
            }
        }
       
$code .= 'return 0;';
       
$compare = create_function('$a,$b', $code);
       
usort($array, $compare);
        return
$array;
    }
?>
up
5
Hayley Watson
10 years ago
As the documentation says, the comparison function needs to return an integer that is either "less than, equal to, or greater than zero". There is no requirement to restrict the value returned to -1, 0, 1.

<?php
usort
($array, function($a, $b) {
    if(
$a->integer_property > $b->integer_property) {
        return
1;
    }
    elseif(
$a->integer_property < $b->integer_property) {
        return -
1;
    }
    else {
        return
0;
    }
});
?>

can be simplified to

<?php
usort
($array, function($a, $b) {
    return
$a->integer_property - $b->integer_property;
});
?>

This of course applies to any comparison function that calculates an integer "score" for each of its arguments to decide which is "greater".
up
11
mkr at binarywerks dot dk
21 years ago
If you want to sort an array according to another array acting as a priority list, you can use this function.

<?php
function listcmp($a, $b)
{
  global
$order;

  foreach(
$order as $key => $value)
    {
      if(
$a==$value)
        {
          return
0;
          break;
        }

      if(
$b==$value)
        {
          return
1;
          break;
        }
    }
}

$order[0] = "first";
$order[1] = "second";
$order[2] = "third";

$array[0] = "second";
$array[1] = "first";
$array[2] = "third";
$array[3] = "fourth";
$array[4] = "second";
$array[5] = "first";
$array[6] = "second";

usort($array, "listcmp");

print_r($array);
?>
up
5
svenxy AT nospam gmx net
17 years ago
This will sort subnets correctly:

<?php

$zones
=
array(
'192.168.11',
'192.169.12',
'192.168.13',
'192.167.14',
'192.168.15',
'122.168.16',
'192.168.17'
);

function
sort_subnets ($a, $b) {
   
$a_arr = explode('.', $a);
   
$b_arr = explode('.', $b);
    foreach (
range(0,3) as $i) {
        if (
$a_arr[$i] < $b_arr[$i] ) {
            return -
1;
        }
        elseif (
$a_arr[$i] > $b_arr[$i] ) {
            return
1;
        }
    }
    return -
1;
}

usort($zones, 'sort_subnets');
print
'<pre>';
print_r($zones);
print
'</pre>';

?>
up
3
alex at netflex dot nl
21 years ago
This function will sort on more then one values, test and have fun

<pre>
<?php

  $array
[0]['name'] = "a";
 
$array[0]['id'] = 3;

 
$array[1]['name'] = "a";
 
$array[1]['id'] = 2;

 
$array[2]['name'] = "a";
 
$array[2]['id'] = 5;

 
$array[3]['name'] = "b";
 
$array[3]['id'] = 8;

 
$array[4]['name'] = "b";
 
$array[4]['id'] = 1;

 
$array[5]['name'] = "b";
 
$array[5]['id'] = 0;

 
$array[6]['name'] = "c";
 
$array[6]['id'] = 5;

 
$array[7]['name'] = "c";
 
$array[7]['id'] = 7;

 
$array[8]['name'] = "c";
 
$array[8]['id'] = 3;

 
print_r($array);

 
$sort_array[0]['name'] = "name";
 
$sort_array[0]['sort'] = "ASC";
 
$sort_array[0]['case'] = TRUE;

 
$sort_array[1]['name'] = "id";
 
$sort_array[1]['case'] = FALSE;

 
sortx($array, $sort_array);

 
print_r($array);

  function
sortx(&$array, $sort = array()) {
   
$function = '';
    while (list(
$key) = each($sort)) {
      if (isset(
$sort[$key]['case'])&&($sort[$key]['case'] == TRUE)) {
       
$function .= 'if (strtolower($a["' . $sort[$key]['name'] . '"])<>strtolower($b["' . $sort[$key]['name'] . '"])) { return (strtolower($a["' . $sort[$key]['name'] . '"]) ';
      } else {
       
$function .= 'if ($a["' . $sort[$key]['name'] . '"]<>$b["' . $sort[$key]['name'] . '"]) { return ($a["' . $sort[$key]['name'] . '"] ';
      }
      if (isset(
$sort[$key]['sort'])&&($sort[$key]['sort'] == "DESC")) {
       
$function .= '<';
      } else {
       
$function .= '>';
      }
      if (isset(
$sort[$key]['case'])&&($sort[$key]['case'] == TRUE)) {
       
$function .= ' strtolower($b["' . $sort[$key]['name'] . '"])) ? 1 : -1; } else';
      } else {
       
$function .= ' $b["' . $sort[$key]['name'] . '"]) ? 1 : -1; } else';
      }
    }
   
$function .= ' { return 0; }';
   
usort($array, create_function('$a, $b', $function));
  }

?>
</pre>
up
3
bo at erichsen dot com
22 years ago
when using usort to refer to a function inside a class i have succesfully used:

<?php usort($myarray,array($this,"cmp")); ?>
up
2
me at evertpot dot com
8 years ago
I see many people here (including the official examples) write their callbacks rather clumsily like this:

<?php
function($a, $b) {
  if (
$a === $b) {
    return
0;
  } elseif (
$a < $b) {
    return -
1
  } else {
    return
1;
  }
}
?>

Or if they are a bit more clever:

<?php
function($a, $b) {

  if (
$a === $b) {
    return
0;
  } else {
    return
$a < $b ? -1 : 1;
  }
}
?>

But this can by simplified further to:

<?php
function($a, $b) {
  return
$a - $b;
}
?>
up
2
Jian Wu
11 years ago
The usort function actually moves $b up when the callback function returns both 0 and 1.  If you want to preserve the original order in the array, return 1 when $a == $b instead of 0.  Try this code below to see how usort alters the order of the original array when all values are the same.

<?php
class TestObj {
    private
$name;
    private
$id;

    function
TestObj($name, $id) {
       
$this->name = $name;
       
$this->id = $id;
    }

    static function
cmp_obj($a, $b) {
       
$al = strtolower($a->name);
       
$bl = strtolower($b->name);
        if (
$al == $bl) {
            return
0; // return 1 if you don't want $b to go in front of $a
       
}
        return (
$al > $bl) ? +1 : -1;
    }
}

$a[] = new TestObj("a", 1);
$a[] = new TestObj("a", 2);
$a[] = new TestObj("a", 3);

var_dump($a);
usort($a, array("TestObj", "cmp_obj"));
var_dump($a);
?>
up
3
drorasta
15 years ago
Here's how you can usort() a multidimensional array (like in example #2 above) within a class:

<?php usort($myArray, array("className", "cmp")); ?>
up
1
sydney at totoche dot org
18 years ago
Instead of doing  :

<?php $strc = strcmp( strtolower($a[$f]), strtolower($b[$f]) ); ?>

you could do this :

<?php $strc = strcasecmp( $a[$f], $b[$f] ); ?>

which is more efficient and is does case insensitive comparison according to the current locale.
up
2
franky at iname dot com
22 years ago
For sort multi-array by specific index

<?php
function cmp ($a, $b)
{  
global
$w_o;
if (
$a[$w_o] == $b[$w_o]) return 0;
return (
$a[$w_o] < $b[$w_o]) ? -1 : 1;
}
# the index is the second element of
# each row

$w_o =1;
usort($my_arry_info,"cmp");
?>
up
2
derek at luddite dot net
23 years ago
Needed a date sort and I didn't know if one was available so I wrote one. Maybe it'll help someone:

<?php
function DateSort($a,$b,$d="-") {
    if (
$a == $b) {
        return
0;
    } else { 
//Convert into dates and compare
       
list($am,$ad,$ay)=split($d,$a);
        list(
$bm,$bd,$by)=split($d,$b);
        if (
mktime(0,0,0,$am,$ad,$ay) < mktime(0,0,0,$bm,$bd,$by)) {
            return -
1;
        } else {
            return
1;
        }
    }
}
?>

$d is the delimeter
up
2
jalil at measat dot org
15 years ago
<?php
/*---------------------------------------------------------
* my own home made easy object sort, which
* i cannot find anywhere on the net
* at all, tut. i can find only complicated ones,
* which brings me a headache.
*
* You can enhance it to return all sorts of error
* conditions if you wish,
* i need nothing but a false return upon failure to sort,
* so that is the only error i have here
*
* Example usage:
*
* INPUT                 -       $objects_array
// an array of objects for sorting

* PARAMETERS    -       property
// the property of the object to be sorted

* OUTPUT                -       $engine
// an engine object created by new,
// with your arrays of objects sorted according to your
// selected property
//( the sorting is done upon sort object creation )
*
* Code Examples
*
* $engine = new objSorter($objects_array);
// sorts on FIRST property -  default

* $engine = new objSorter($objects_array,'property');
// sort on ANY specific property
*--------------------------------------------------------*/

class objSorter
{
var
$property;
var
$sorted;

    function
ObjSorter($objects_array,$property=null)
        {
           
$sample    = $objects_array[0];
           
$vars    = get_object_vars($sample);

        if (isset(
$property))
            {
            if (isset(
$sample->$property))
// make sure requested property is correct for the object
               
{   
               
$this->property = $property;
               
usort($objects_array, array($this,'_compare'));
                }
            else
                {   
               
$this->sorted    = false;
                return;   
                }
            }
        else
            {   
                list(
$property,$var)     = each($sample);
               
$this->property         = $property;
               
usort($objects_array, array($this,'_compare'));
            }

       
$this->sorted    = ($objects_array);
        }

    function
_compare($apple, $orange)
        {
       
$property    = $this->property;
        if (
$apple->$property == $orange->$property) return 0;
        return (
$apple->$property < $orange->$property) ? -1 : 1;
        }
}
// end class
?>

USAGE EXAMPLE
DUMP ORIGINAL
user Object ( [name] => Yunihe Jopoba [age] => 27 [richness] => € 899,970 )
user Object ( [name] => Janirevi Fakejorumoa [age] => 19 [richness] => € 219,078 )
user Object ( [name] => Korejowi Mezede [age] => 95 [richness] => € 3,272 )
user Object ( [name] => Nugoaivu Jongyi [age] => 84 [richness] => € 94,853 )
user Object ( [name] => Cepomase Buaesukoyua [age] => 32 [richness] => € 677,180 )
user Object ( [name] => Vejosehona Auva [age] => 20 [richness] => € 144,540 )
user Object ( [name] => Fewame Wojuvuzo [age] => 69 [richness] => € 198,231 )
user Object ( [name] => Risuku Zagedobu [age] => 48 [richness] => € 763,860 )
user Object ( [name] => Fazurada Aayu [age] => 16 [richness] => € 302,352 )

SORTED by age

<?php
$objects               
= new ObjSorter($objects_array,'age');
if (
$objects->sorted)
{
$objects_array  = $objects->sorted;
foreach (
$objects_array as $key=>$object) { print_r($object); echo "<br />"; }
}
?>

user Object ( [name] => Fazurada Aayu [age] => 16 [richness] => € 302,352 )
user Object ( [name] => Janirevi Fakejorumoa [age] => 19 [richness] => € 219,078 )
user Object ( [name] => Vejosehona Auva [age] => 20 [richness] => € 144,540 )
user Object ( [name] => Yunihe Jopoba [age] => 27 [richness] => € 899,970 )
user Object ( [name] => Cepomase Buaesukoyua [age] => 32 [richness] => € 677,180 )
user Object ( [name] => Risuku Zagedobu [age] => 48 [richness] => € 763,860 )
user Object ( [name] => Fewame Wojuvuzo [age] => 69 [richness] => € 198,231 )
user Object ( [name] => Nugoaivu Jongyi [age] => 84 [richness] => € 94,853 )
user Object ( [name] => Korejowi Mezede [age] => 95 [richness] => € 3,272 )

SORTED by richness

<?php
$objects               
= new ObjSorter($objects_array,'richness');
if (
$objects->sorted)
{
$objects_array  = $objects->sorted;
foreach (
$objects_array as $key=>$object) { print_r($object); echo "<br />"; }
}
?>

user Object ( [name] => Vejosehona Auva [age] => 20 [richness] => € 144,540 )
user Object ( [name] => Fewame Wojuvuzo [age] => 69 [richness] => € 198,231 )
user Object ( [name] => Janirevi Fakejorumoa [age] => 19 [richness] => € 219,078 )
user Object ( [name] => Korejowi Mezede [age] => 95 [richness] => € 3,272 )
user Object ( [name] => Fazurada Aayu [age] => 16 [richness] => € 302,352 )
user Object ( [name] => Cepomase Buaesukoyua [age] => 32 [richness] => € 677,180 )
user Object ( [name] => Risuku Zagedobu [age] => 48 [richness] => € 763,860 )
user Object ( [name] => Yunihe Jopoba [age] => 27 [richness] => € 899,970 )
user Object ( [name] => Nugoaivu Jongyi [age] => 84 [richness] => € 94,853 )

Simulated wrong property request ( dumb property )

<?php
$objects               
= new ObjSorter($objects_array,'dumb property');
if (
$objects->sorted)
{
$objects_array  = $objects->sorted;
foreach (
$objects_array as $key=>$object) { print_r($object); echo "<br />"; }
}
else echo
'DUMB ERROR';
?>

DUMB ERROR
up
2
admin at gosenz dot com
12 years ago
sort multi-dimentional arrays in class with usort

<?php
class ArraySort
{
    private
$arr = array();

    public function
__construct($arr)
    {
       
$this->arr = $arr;
    }

    public function
doSort()
    {
       
$cmp = function($a, $b)
        {
           
//Do Some Comparation
       
}
        if(
is_array($this->arr))
        {
           
usort($this->arr, $cmp);
        }
        return
$this->arr;
    }
}
?>
up
1
Lea Hayes
12 years ago
<?php
/**
* Sort array of objects by field.
*
* @param array $objects Array of objects to sort.
* @param string $on Name of field.
* @param string $order (ASC|DESC)
*/
function sort_on_field(&$objects, $on, $order = 'ASC') {
   
$comparer = ($order === 'DESC')
        ?
"return -strcmp(\$a->{$on},\$b->{$on});"
       
: "return strcmp(\$a->{$on},\$b->{$on});";
   
usort($objects, create_function('$a,$b', $comparer));
}
?>
up
1
bcsj
12 years ago
Sorting a multidimensional array by a subkey seem to be one of the bigger challenges when using usort. At least if one want the key to be dynamic. For anyone interested this code seemed to work rather well for me:

<?php

usort
($array,array(new cmp($key), "cmp__"));

class
cmp {
    var
$key;
    function
__construct($key) {
       
$this->key = $key;
    }
   
    function
cmp__($a,$b) {
       
$key = $this->key;
        if (
$a[$key] == $b[$key]) return 0;
        return ((
$a[$key] > $b[$key]) ? 1 : -1);
    }
}

?>
up
2
andi_mclean at ntlworld dot com
12 years ago
I needed a sort method that would sort strings but take note of any numbers and would compare them as number. I also want to ignore any non alphanumerical characters.

Eg.
Slot 1 Example
Slot 10 Example
Slot 2 Example

Should infact be
Slot 1 Example
Slot 2 Example
Slot 10 Example

<?php
function sort_with_numbers($a , $b) {
   
$a = explode(' ',$a);
   
$b = explode(' ',$b);
   
$size = min(count($a), count($b));
    for(
$index =0; $index < $size; ++$index) {
       
$a1 = ereg_replace("[^A-Za-z0-9]", "",$a[$index]);
       
$b1 = ereg_replace("[^A-Za-z0-9]", "",$b[$index]);
       
$equal = 0;
        if (
is_numeric($a1) && is_numeric($b1)) {
           
$equal = $a1 - $b1;
        } else {
           
$equal = strcasecmp($a1,$b1);
        }
        if (
$equal < 0) {
            return -
1;
        }
        if (
$equal > 0) {
            return
1;
        }
    }
    return
count($a) - count($b);   
}
?>
up
1
prozac at iguanasoft dot com
21 years ago
Here is a simple example of converting a timestamp date("U") into a date. This sorts by that day and then by string value alphabetically.

I hope it saves someone some time... Happy PHP'in!

<?php
//data to sort
$shared[0]["page_id"] = "2025731470";
$shared[1]["page_id"] = "2025731450";
$shared[2]["page_id"] = "1025731456";
$shared[3]["page_id"] = "1025731460";
$shared[0]["username"] = "larry";
$shared[1]["username"] = "alvin";
$shared[2]["username"] = "garth";
$shared[3]["username"] = "harvy";

//function to convert timestamp to date
function convert_timestamp($timestamp){
   
$limit=date("U");
   
$limiting=$timestamp-$limit;
    return
date ("Ymd", mktime (0,0,$limiting));
}
//comparison function
function cmp ($a, $b) {
   
$l=convert_timestamp($a["page_id"]);
   
$k=convert_timestamp($b["page_id"]);
    if(
$k==$l){
        return
strcmp($a["username"], $b["username"]);
    }else{
        return
strcmp($k, $l);
    }
}

//sort array
usort($shared, "cmp");

//display sorted info
while (list ($key, $value) = each ($shared)) {
    echo
"\$shared[$key]: ";
    echo
$value["page_id"];
    echo
" username: ";
    echo
$value["username"];
    echo
"<break_tag>";
}
?>

This will output:
$shared[0]: 2025731450   username: alvin
$shared[1]: 2025731470   username: larry
$shared[2]: 1025731456   username: garth
$shared[3]: 1025731460   username: harvy
up
1
gus dot antoniassi at gmail dot com
4 years ago
This is a simple way to sort based on a "priority list":

<?php

$order
= [1,3,0,2];
$arr =   [
    [
'id' => 0 ],
    [
'id' => 1 ],
    [
'id' => 2 ],
    [
'id' => 3 ],
];

uasort(
   
$arr,
    function (
$a, $b) use ($order) {
        return
array_search($a['id'], $order) <=> array_search($b['id'], $order);
    }
);

print_r($arr);

?>

This will return:

Array
(
    [1] => Array
        (
            [id] => 1
        )

    [3] => Array
        (
            [id] => 3
        )

    [0] => Array
        (
            [id] => 0
        )

    [2] => Array
        (
            [id] => 2
        )

)

Note that if you have a value in $arr that is not on the $order list, you will need additional checks since the array_search function returns FALSE for undefined indexes.
up
2
inigo dot grimbergen at gmail dot com
7 years ago
to sort with numeric and empty values  and have the smallest on top:
<?php
    usort
($list, function($a, $b) {
        if(
$a == null && $b != null ) return 1;
        if(
$a != null && $b == null ) return -1;
        return
$a > $b ? 1 : -1;
    });
?>
returns
1
2
3
null
null
null
up
0
jab_creations at yahoo dot com
2 years ago
The usort function should not be used for associative arrays where the base keys need to retain their names, otherwise this:

$a = array('example' => 'hello');

Will be converted to:

$a = array(0 => 'hello');

To retain key names in associative arrays you can simply replace usort with uasort; for me it was a drop-in replacement without having to change anything else.
up
0
chris at candm dot org dot uk
5 years ago
In case anyone is interested, comparative timings over 100000000 runs
Based on comparing integers (500 and 501)
Spaceship:4
()?: operator:10
Subtraction:2

Based on comparing floats (500.1 and 501.3) (caveats noted)
Spaceship:5
()?: operator:9
Subtraction:3

Based on comparing strings ("five" and "four")
Spaceship:7
()?: operator:17
(Subtraction obviously not available)

Note: a dummy run was done with an empty loop and the elapsed time for this was subtracted from each of the above times so that they reflect ONLY the time to do the comparisons. As for significance. unless you are doing very large numbers of comparisons where spaceships are the order of the day, the difference is insignificant.
up
0
Jeremy Swinborne
18 years ago
When I query a DB I usually put my record set inside of a multi-dimentional array.  I finally wrote a program that will allow you to sort your record set by column after you put it in an array.

<?php
$test
= array();
$test[0]['name'] = 'jeremy';
$test[0]['email'] = 'lala@example.com';
$test[0]['phone'] = '123-123-1234';
$test[0]['trick'] = 'mezopia';

$test[1]['name'] = 'Amanda';
$test[1]['email'] = 'hot@example.com';
$test[1]['phone'] = '123-123-1235';
$test[1]['trick'] = 'youarecool';

$test[2]['name'] = 'john';
$test[2]['email'] = 'wowee@example.com';
$test[2]['phone'] = '123-123-3333';
$test[2]['trick'] = 'goneinanhour';

print_r(columnSort($test, 'name'));

function
columnSort($unsorted, $column) {
   
$sorted = $unsorted;
    for (
$i=0; $i < sizeof($sorted)-1; $i++) {
      for (
$j=0; $j<sizeof($sorted)-1-$i; $j++)
        if (
$sorted[$j][$column] > $sorted[$j+1][$column]) {
         
$tmp = $sorted[$j];
         
$sorted[$j] = $sorted[$j+1];
         
$sorted[$j+1] = $tmp;
      }
    }
    return
$sorted;
}
?>
up
-1
skrebbel at operamail dot com
20 years ago
here's another recursive multisort, however a clean and fast one that is class-based (but works as well outside classes) and does not uglify your global namespace at all. note that strnatcmp is used, but one could use something else of course.

btw, for arrays in which the rows/columns are 'swapped', use array_multisort().

<?php
class Banana {
    var
$aData;//the array we want to sort.
   
var $aSortkeys;//the order in which we want the array to be sorted.
   
function _sortcmp($a, $b, $i=0) {
       
$r = strnatcmp($a[$this->aSortkeys[$i]],$b[$this->aSortkeys[$i]]);
        if(
$r==0) {
           
$i++;
            if (
$this->aSortkeys[$i]) $r = $this->_sortcmp($a, $b, $i+1);
        }
        return
$r;
    }
    function
sort() {
        if(
count($this->aSortkeys)) {
           
usort($this->aData,array($this,"_sortcmp"));
        }
    }
}
$B = new Banana;
$B->aData = array(
    array(
"name" => "hank", "headsize" => "big", "age" => 32),
    array(
"name" => "frank", "headsize" => "huge", "age" => 36)
);
$B->aSortkeys = array("age","name");
$B->sort();

?>
sorry for the ugly indenting, but i couldn't get it any better in this note adder thing.
To Top