PHP使用使用者自定義的比較函式對陣列中的值進行排序

傑克.陳發表於2014-12-13

原文:PHP 使用使用者自定義的比較函式對陣列中的值進行排序

 

  

usort

   

(PHP 4, PHP 5)

usort —      使用使用者自定義的比較函式對陣列中的值進行排序    

  

說明

    

      bool usort        ( array &$array       , callable $cmp_function       )

   

     本函式將用使用者自定義的比較函式對一個陣列中的值進行排序。如果要排序的陣列需要用一種不尋常的標準進行排序,那麼應該使用此函式。    

Note:    

     如果兩個成員比較結果相同,則它們在排序後的陣列中的順序未經定義。    

 

Note: 此函式為 array 中的元素賦與新的鍵名。這將刪除原有的鍵名,而不是僅僅將鍵名重新排序。

引數

  

     array     
     

       輸入的陣列      

    

     cmp_function     
     

       在第一個引數小於,等於或大於第二個引數時,該比較函式必須相應地返回一個小於,等於或大於 0 的整數。      

     

int callback ( mixed $a, mixed $b )

      

Caution       

        Returning non-integer values from the comparison         function, such as float, will result in an internal cast to         integer of the callback`s return value. So values such as         0.99 and 0.1 will both be cast to an integer value of 0, which will         compare such values as equal.       

     

    

 

返回值

   成功時返回 TRUE, 或者在失敗時返回 FALSE

更新日誌

  

                                                                                  

版本 說明
4.1.0         引進了新的排序演算法。使用者自定義函式 cmp_function 將不再保留這些單元的原有順序。       

 

範例

  

   

Example #1  usort() 例子

   

<?php function cmp($a$b)
{     
if ($a == $b
{         return 0;     }     
return ($a $b) ? -1; }
$a = array(32561);
usort($a"cmp");
foreach ($a as $key => $value)
 {     echo "$key$value
"; } ?>

   

   

以上例程會輸出:

   

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

   

  

 

Note:   

    很明顯在這個小例子中用  sort() 函式更合適。   

 

  

   

Example #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");
while (list($key$value) = each($fruits)) 
{     echo "$fruits[$key]: " $value["fruit"] . "
"; } ?>

   

   

     當排序多維陣列時,$a 和 $b 包含到陣列第一個索引的引用。    

   

以上例程會輸出:

   

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

   

  

 

  

   

Example #3       usort() example using a member function of an object    

   

 
<?php 

class TestObj {     var $name;
    function TestObj($name)     

{         $this->name = $name;     }
    /* This is the static comparing function: */    

 static function cmp_obj($a, $b)     

{        

 $al = strtolower($a->name);         

$bl = strtolower($b->name);         

if ($al == $bl) {             return 0;         }         

return ($al > $bl) ? +1 : -1;     } }
$a[] = new TestObj("c"); $a[] = new TestObj("b"); $a[] = new TestObj("d");
usort($a, array("TestObj", "cmp_obj"));
foreach ($a as $item)

 {     echo $item->name . "
"; }

?> 
    

 

   

以上例程會輸出:

   

b
c
d

   

  

   

   

Example #4       usort() example using a closure      to sort a multi-dimensional array    

   

<?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($arraybuild_sorter(`key_b`));
foreach ($array as $item
{     echo $item[`key_a`] . `, ` $item[`key_b`] . "
"; } ?>

   

   

以上例程會輸出:

   

y, a
x, b
z, c

   

  

 

參見

  

 

 


 

   

線上手冊:中文      英文

 

使用者評論:

Hayley Watson (2013-04-08 22:30:19)

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".

hexarobi at gmail dot com (2013-02-21 21:04:32)

Needed to sort an array of objects based on multiple properties. (ie: Group, then Last Name, then First Name) Doing this in multiple usorts fails because the second usort ends up shuffling the results of the previous usort because order is undefined when criteria are equal. Ended up writing a function that builds a comparison operator by nesting ternary operators for each field, then using that function in usort(). Hopefully it`s of use to someone else.

<?php
/*
 * Sorts an array of objects by a list of properties.
 * Each property can have the following options:
 *   `property` can be either a public variable or a method().
 *   `order` can be ASC or DESC
 *   `comparer` can be string, number, or date
 * 
 * Example:
 * sortObjectsByProperties($objects, array(
 *       array(`property`=>`getPrice()`, order=>`ASC`, `comparer`=>`number`),
 *       array(`property`=>`getName()`, order=>`DESC`, `comparer`=>`string`),
 *       array(`property`=>`created_date`, order=>`ASC`, `comparer`=>`date`),
 *       array(`property`=>`id`, order=>`ASC`, `comparer`=>`number`),
 *   ));
 * 
 * @author Tyler Chamberlain
 */
function sortObjectsByProperties(&$objects$fields) {
        $comparerFunctionString "";
        foreach ($fields as $field) {
            if ($field[`comparer`] == `number`) {
                $comparerFunction "($a->{$field[`property`]} == $b->{$field[`property`]} ? 0 : ($a->{$field[`property`]} > $b->{$field[`property`]} ? 1 : -1))";
            } elseif ($field[`comparer`] == `date`) {
                $comparerFunction "(strtotime($a->{$field[`property`]}) > strtotime($b->{$field[`property`]}) ? 1 : -1)";
            } else {
                $comparerFunction "strcasecmp($a->{$field[`property`]},$b->{$field[`property`]})";
            }
            if ($field[`order`] === `DESC`) { $comparerFunction "-".$comparerFunction; }
            $comparerFunctionString .= "$comparerFunction != 0 ? $comparerFunction : (";
        }
        $comparer "return ($comparerFunctionString 0 )".str_repeat(")"sizeof($fields)).";";
        usort($objectscreate_function(`$a,$b`$comparer)); 
}
?>

Jian Wu (2012-07-06 21:16:20)

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;
    }
}

$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);
?>

zuallauz at gmail dot com (2012-03-29 21:56:45)

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(58373);
usort($priorities, function($a$b) {     if ($a == $b)     {         echo "a ($a) is same priority as b ($b), keeping the same
";         return 0;     }     else if ($a $b)     {         echo "a ($a) is higher priority than b ($b), moving b down array
";         return -1;     }     else {         echo "b ($b) is higher priority than a ($a), moving b up array
";                         return 1;     } });
echo "Sorted priorities:
"; 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) }

andi_mclean at ntlworld dot com (2012-02-04 15:58:08)

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);     } ?>

Quicker (2012-01-05 13:53:43)

This one may approve multisort performance dramatically.

I had a 100K-row-array with assoc keys and sub arrays, several MBs. Using usort hammered my dev box cpu for several minutes until I killed it. 
My own assoc-version of [someone else`s code] did the same. Following Array-Indexing and sorting solution only took very few secs:

<?php
define(`funcname`,0);
define(`indexfieldinfuncparamspos`,1);
define(`funcparams`,2);
function array_index($dataarr,$field2funcarr){
  $indexarr=array();
  foreach($dataarr as $key=>$valarr) {
    $currentindex=``;
    foreach($field2funcarr as $fieldid=>$funcarr) if(is_array($funcarr)) {
      $funcarr[funcparams][$funcarr[indexfieldinfuncparamspos]]= $valarr[$fieldid];
      $currentindex.= call_user_func_array($funcarr[funcname],$funcarr[funcparams]).`_`
    } else $currentindex.= $valarr[$fieldid].`_`;
    $indexarr[$currentindex]=$key;
  }
  return $indexarr;
}
function array_sortbyindex(&$dataarr,$indexarr,$issortindexbykey=true){
  // assumes complete index!: each item of indexarr must correlate a key of dataarr
  $resultarr=array();
  if($issortindexbykeyksort($indexarr);
  foreach($indexarr as $datakey$resultarr[$datakey]= $dataarr[$datakey];
  return $resultarr;
}

$dataarr=array(
`Franz`=>array(`letters`=>5,`wordtype`=>`name`),
`goes`=>array(`letters`=>4,`wordtype`=>`verb`),
`to`=>array(`letters`=>2,`wordtype`=>`prep`),
`China`=>array(`letters`=>5,`wordtype`=>`noun`));

// just build an index for interest (empty string for wordtype as no modification required):
print_r(array_index($dataarr, array(`letters`=>array(`str_pad`,0,array(``,7,`0`,STR_PAD_LEFT)), `wordtype`=>``)));

// build index and sort - all in one go:
print_r(array_sortbyindex($dataarrarray_index($dataarr, array(`letters`=>array(`str_pad`,0, array(``,7,`0`,STR_PAD_LEFT)), `wordtype`=>``))));
?>

first print_r returns:
Array
(
    [0000005_name_] => Franz
    [0000004_verb_] => goes
    [0000002_prep_] => to
    [0000005_noun_] => China
)

second print_r returns:
Array
(
    [to] => Array
        (
            [letters] => 2
            [wordtype] => prep
        )

    [goes] => Array
        (
            [letters] => 4
            [wordtype] => verb
        )

    [Franz] => Array
        (
            [letters] => 5
            [wordtype] => name
        )

    [China] => Array
        (
            [letters] => 5
            [wordtype] => noun
        )

)

Major Benefits:
- extremly fast
- each sort field can apply an own modifier. Ideally you can use out-of-the-box functions, which reduces effort for programming callbacks
- you could use the index eg. for sorted data output without physically sorting the data

admin at gosenz dot com (2011-12-04 20:58:38)

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;     } } ?>

Gok6tm (2011-09-13 06:09:10)

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($args01);
    $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 == && $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
        )

)

neculitairinel at yahoo dot com (2011-08-19 06:12:51)

Here is another date sort, in case you have hours and minutes in the dates.

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

Lea Hayes (2011-07-12 17:55:13)

<?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($objectscreate_function(`$a,$b`$comparer));
}
?>

bcsj (2011-06-28 11:12:43)

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);     } }
?>

masonswolf+ignorethispart at gmail dot com (2011-06-13 10:42:03)

[The second version of a function I wrote], just a little cleaner to use, since the usort call is now folded into the custom `usortByArrayKey` function.

Seems like this is a popular problem - sorting an array of arrays by the keys of sub-arrays, so I`ll go ahead and throw in an approach I haven`t seen anyone mention yet. It only works since PHP 5.3 because that`s when anonymous functions got added to the language. 

<?php 
function usortByArrayKey(&$array$key$asc=SORT_ASC) { 
    $sort_flags = array(SORT_ASCSORT_DESC); 
    if(!in_array($asc$sort_flags)) throw new InvalidArgumentException(`sort flag only accepts SORT_ASC or SORT_DESC`); 
    $cmp = function(array $a, array $b) use ($key$asc$sort_flags) { 
        if(!is_array($key)) { //just one key and sort direction 
            if(!isset($a[$key]) || !isset($b[$key])) { 
                throw new Exception(`attempting to sort on non-existent keys`); 
            } 
            if($a[$key] == $b[$key]) return 0
            return ($asc==SORT_ASC xor $a[$key] < $b[$key]) ? : -1
        } else { //using multiple keys for sort and sub-sort 
            foreach($key as $sub_key => $sub_asc) { 
                //array can come as `sort_key`=>SORT_ASC|SORT_DESC or just `sort_key`, so need to detect which 
                if(!in_array($sub_asc$sort_flags)) { $sub_key $sub_asc$sub_asc $asc; } 
                //just like above, except `continue` in place of return 0 
                if(!isset($a[$sub_key]) || !isset($b[$sub_key])) { 
                    throw new Exception(`attempting to sort on non-existent keys`); 
                } 
                if($a[$sub_key] == $b[$sub_key]) continue; 
                return ($sub_asc==SORT_ASC xor $a[$sub_key] < $b[$sub_key]) ? : -1
            } 
            return 0
        } 
    };
    usort($array$cmp);
}; 
?>

Examples: 
1) Sort a multi-dimensional array by a single key, from least to greatest: 
    usortByArrayKey($resultset, `order_id`); 

2) Sort a multi-dimensional array by a single key, from greatest to least: 
    usortByArrayKey($resultset, `purchase_amount`, SORT_DESC); 

3) Sort a multi-dimensional array first by one key, but then by a different key when the first one is equal, both from least to greatest: 
    usortByArrayKey($resultset, array(`product_id`, `price`)); 

4) Sort a multi-dimensional array by two different keys from least to greatest, and then a third from greatest to least if the first two keys map to the equal values: 
    usortByArrayKey($resultset, array(`product_id`, `customer_id`, `date`=>SORT_DESC)); 

5) Sort a multi-dimensional array by multiple keys, all from greatest to least: 
    usortByArrayKey($resultset, array(`product_id`, `price`), SORT_DESC);

One word of caution, since SORT_ASC and SORT_DESC have actual int values of 4 and 3, respectively, if you need to sort a multi-dimensional array by keys 3 or 4, and you`re using an array to pass in your keys, you MUST specify your sort flags (e.g. array(3 => SORT_ASC,...)) to prevent unexpected behavior, instead of relying on the function`s second parameter as your default sort flag.

cuonghuyto at gmail dot com (2011-03-02 02:42:09)

Some contribution towards a specification of usort()
——
– If you don`t provide the callback function, an error would be raised: “usort(): Invalid comparison function.”
– If your callback function doesn`t return anything, or returns any value other than -1 or +1 (e.g. 0, 2, -2), then usort() would treat your sorting purpose as if there is no comparison operator provided, and it would actually change your list into an undefined order
——

markfiend at gmail dot com (2011-02-21 02:22:41)

To sort a multidimensional array (such as is returned from database query) by the values in $array[foo][$key]
e.g.  <?php /** Potential pitfall if there is already a key of `__________`  *  in the subarrays. Not likely I hope!  * -------------------------------------------------------------  */ function array_sort_by_subval(&$array$key) {     foreach($array as &$v) {         $v[`__________`] = $v[$key];     }     usort($array`sort_by_underscores`);     foreach($array as &$v) {         unset($v[`__________`]);     } }
function sort_by_underscores($a$b) {     if($a[`__________`] == $b[`__________`]) return 0;     if($a[`__________`] < $b[`__________`]) return -1;     return 1; }
$n = array(array(`a` => 0`b` => 7`c` => 2),            array(`a` => 4`b` => 1`c` => 3),            array(`a` => 7`b` => 3`c` => 1));
array_sort_by_subval($n`b`); ?> The array $n will now be: array(array(`a` => 4, `b` => 1, `c` => 3),       array(`a` => 7, `b` => 3, `c` => 1),       array(`a` => 0, `b` => 7, `c` => 2))

cmanley_nl (2011-01-24 11:55:40)

I had to sort a result set by host. I made this comparator function to use in usort calls.
Sorts by host segment so that a.example.org comes after b.example.com, etc.

<?php
function hostcmp($a$b) {
    $a strtolower($a);
    $b strtolower($b);
    if ($a == $b) {
        return 0;
    }
    $parts_a array_reverse(explode(`.`$a));
    $parts_b array_reverse(explode(`.`$b));
    $max max(count($parts_a), count($parts_b));
    for ($i=0$i $max$i++) {
        if (($i count($parts_a)) && ($i count($parts_b))) {
            if ($c strcmp($parts_a[$i],$parts_b[$i])) {
                return $c;
            }
        }
        else {
            // Return numeric cmp on array sizes. PHP doesn`t have a <=> operator, so emulate it.
            //return count($parts_a) <=> count($parts_b);
            return count($parts_a) == count($parts_b) ? : (count($parts_a) < count($parts_b) ? -1);
        }
    }
    return 0;
}
?>

fmaz008 at gmail dot com (2010-09-29 14:23:36)

This comment is just to help backward compatibility.
I needed to have a foreach loop using reference just before using the usort function on the same array that was used in the foreach.
Like this: <?php public function sortByTitle() {         if(empty($this->_arrSubCat))             return false;                  foreach($this->_arrSubCat as &$cat)             $cat->sortByTitle();                  usort($this->_arrSubCat`strcasecmp`); } ?> I had this strange bug where the last object of the $this->_arrSubCat array before the sort was alway replaced/overwrited with his string value.
On my machine (PHP 5.3), I had no problem, but when I placed the code on another server, my code crashed with a fatal error (Because I was using a string as an object later in the code)
The solution I found is really simple, and avoid the array to have a reference declared in memory while running the sort function. Just add an unset($cat):
<?php public function sortByTitle() {         if(empty($this->_arrSubCat))             return false;                  foreach($this->_arrSubCat as &$cat)             $cat->sortByTitle();                  unset($cat); //No more problem because of the foreach &cat reference.             usort($this->_arrSubCat`strcasecmp`); } ?> It took me an hour an a half to locate the bug, hope it will save someone some time !

phil at lavin dot me dot uk (2010-08-01 11:06:07)

strcmp (or strcasecmp) can be used as a callback function for usort. It will cast your comparison values to string. Thus, you can implement a __toString() method into your classes and use usort without creating a callback function:
<?php class Foo {    private $a;    private $b;
   public function __construct($a$b) {       $this->$a;       $this->$b;    }
   public function __toString() {       return (string)$this->a;    } }
$foo = array(new Foo(`t``b`), new Foo(`a``c`), new Foo(`g``d`));
print_r($foo);
usort($foo`strcasecmp`);
print_r($foo); ?>

xaguilars at gmail dot com (2010-05-06 04:03:29)

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;     } } ?>

Alex Rath (2010-04-17 11:35:51)

This is the perfect Place for anonymous Functions, here an Example:
<?php
  $array = array(32561);
  usort($array, function($func_a$func_b) {     if($func_a == $func_b) return 0;     return ($func_a $func_b) ? -1;   });
  foreach ($array as $key => $value) echo "$key$value
";
?>

nicolas dot demarque at gmail dot com (2010-04-10 11:37:09)

Another way to compare object is to have a compare static function in the class with reccursion ability and have globals or static variables who save the state of comparison, and the order.
It could be a good idea to have a variable with comparison functions name (with the sorting : numeric, alphanumeric, inverse).
<?php interface Comparable{static function compare($a$b);} class myObj implements Comparable{         var $var1; var $var2; var $var3;         function __construct($v1$v2$v3){                 $this->var1=$v1$this->var2=$v2$this->var3=$v3;         }         public function __toString() {                 return "v1 ".$this->var1." v2 ".$this->var2." v3 ".$this->var3;         }         static function compare($a$b){                 $sort=$GLOBALS[`sorts`][$GLOBALS[`sort`]];                 echo "$sort
";                 if($a->$sort == $b->$sort){                         if($GLOBALS[`sorts`][$GLOBALS[`sort`]+1]){                                 $GLOBALS[`sort`]++;                                 $res=  call_user_func(array(`myObj``compare`), $a$b);                                 $GLOBALS[`sort`]=0; return $res;                         }                         $GLOBALS[`sort`]=0; return 0;                 }                 $GLOBALS[`sort`]=0;                 if($a->$sort $b->$sort)                         return 1;                 return -1;         } }
$objects = array(new myObj("1""2""3"), new myObj("2""2""2"), new myObj("1""3""4"));
/* Tests */ $sorts=Array(`var1``var2``var3`); $sort 0usort($objects, array(`myObj``compare`)); echo ("var1 var2 var3
"); foreach($objects as $o)echo $o."
"; $sorts=Array(`var2``var3``var1`); $sort 0usort($objects, array(`myObj``compare`)); echo ("
var2 var3 var1
"); foreach($objects as $o)echo $o."
"; $sorts

相關文章