数组 函数
在线手册:中文  英文

uksort

(PHP 4, PHP 5)

uksort 使用用户自定义的比较函数对数组中的键名进行排序

说明

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

uksort() 函数将使用用户提供的比较函数对数组中的键名进行排序。如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数。

参数

array

输入的数组。

cmp_function

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

int callback ( mixed $a, mixed $b )

返回值

成功时返回 TRUE, 或者在失败时返回 FALSE

范例

Example #1 uksort() 例子

<?php
function cmp($a$b)
{
    
$a preg_replace('@^(a|an|the) @'''$a);
    
$b preg_replace('@^(a|an|the) @'''$b);
    return 
strcasecmp($a$b);
}

$a = array("John" => 1"the Earth" => 2"an apple" => 3"a banana" => 4);

uksort($a"cmp");

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

以上例程会输出:

an apple: 3
a banana: 4
the Earth: 2
John: 1

参见


数组 函数
在线手册:中文  英文

用户评论:

Kieran Clancy (2012-07-15 12:52:10)

Use closures if you want to sort by key AND value:

<?php
/* suppose you want to sort using keys AND values
 *
 * task: Sort this array with highest values first, but if two values
 *       are equal then their keys should be in alphabetical order.
 *
 * solution: use closures.
 */
$stock = array(
    
'apple' => 4,
    
'grape' => 3,
    
'banana' => 3,
    
'pear' => 1,
    
'orange' => 1
);
uksort($stock, function ($a$b) use ($stock) {
    if (
$stock[$a] != $stock[$b]) return $stock[$b] - $stock[$a];
    return 
strcmp($a$b);
});

print_r($stock);
/* output:
Array
(
    [apple] => 4
    [banana] => 3
    [grape] => 3
    [orange] => 1
    [pear] => 1
)
*/
?>

mdsky at web dot de (2010-05-23 11:26:49)

Case insensitive without own function:
uksort($array, "strnatcasecmp");

contacto at hardcode dot com dot ar (2009-07-29 06:56:29)

need a case insensitive sort by key function? i did and couldn find it, so:

<?php
function insensitive_uksort($a,$b) {
    return 
strtolower($a)<strtolower($b);
}
uksort($arr"insensitive_uksort");
?>

brian dot short at gmail dot com (2009-07-07 07:58:15)

If you need to periodically sort by grades (A, A+, D-, etc.), here is a compare function that compares strings by the case-insensitive method, unless it finds a grade, in which case it correctly sorts by putting "plus" grades first, unmarked grades second, and "minus" grades last.

<?php
function cmp($a$b)
{
   
$a preg_replace('@^(a|an|the) @'''$a);
   
$b preg_replace('@^(a|an|the) @'''$b);

   
//special code for grades
   
if (strpos$a"+") !== false || strpos$b"+") !== false  || 
       
strpos$a"-") !== false || strpos$b"-") !== false ){

        
$substrA substr($a01);
        
$substrB substr($b01);        

        
$modifierA = (strlen($a) == 2) ? substr($a11) : "";
        
$modifierB = (strlen($b) == 2) ? substr($b11) : "";
    
        if (
$substrA == $substrB){
            
//figure out plusses and minuses.
            
if ($modifierA == "+"){
                return -
1;
            } else if (
$modifierB == "+"){
                return 
1;
            }
        
            if (
$modifierA == "-"){
                return 
1;
            } else if (
$modifierB == '-'){
                return -
1;
            }
        } else {
            return 
strcasecmp($a$b);
        }
 
    }
   return 
strcasecmp($a$b);
}

$grades = array( 
                 
"C+" => 13    ,
                
"C" => 10     ,
                
"D+" => 8     ,
                
"B+" => 7     ,
                
"C-" => 6     ,
                
"A-" => 5     ,
                
"F" => 5      ,
                
"B" => 4      ,
                
"B-" => 4     ,
                
"D" => 3      ,
                
"D-" => 3     ,
                
"A+" => 1
    
); 

uksort($grades"cmp");
?>

result:  Array
(
    [A+] => 1
    [A-] => 5
    [B+] => 7
    [B] => 4
    [B-] => 4
    [C+] => 13
    [C] => 10
    [C-] => 6
    [D+] => 8
    [D] => 3
    [D-] => 3
    [F] => 5
)

fgallan at gmail dot com (2007-08-02 21:22:16)

muti-array special sort funciton:

<?php
/// mycmp functions ///
function mycmp_asc($a$b) {
    global 
$_CMP_FORMULA;
    static 
$_CMP_FORMULA_VA$_CMP_FORMULA_VB;
    if (!
$_CMP_FORMULA_VA) {
        
$_CMP_FORMULA_VA '$va = ' str_replace('{}''$a'$_CMP_FORMULA) . ';';
    }
    if (!
$_CMP_FORMULA_VB) {
        
$_CMP_FORMULA_VB '$vb = ' str_replace('{}''$b'$_CMP_FORMULA) . ';';
    }
    eval(
$_CMP_FORMULA_VA);
    eval(
$_CMP_FORMULA_VB);
    if (
$va == $vb) return 0;
    else return (
$va $vb ? -1);
}
function 
mycmp_desc($a$b) {
    global 
$_CMP_FORMULA;
    static 
$_CMP_FORMULA_VA$_CMP_FORMULA_VB;
    if (!
$_CMP_FORMULA_VA) {
        
$_CMP_FORMULA_VA '$va = ' str_replace('{}''$a'$_CMP_FORMULA) . ';';
    }
    if (!
$_CMP_FORMULA_VB) {
        
$_CMP_FORMULA_VB '$vb = ' str_replace('{}''$b'$_CMP_FORMULA) . ';';
    }
    eval(
$_CMP_FORMULA_VA);
    eval(
$_CMP_FORMULA_VB);
    if (
$va == $vb) return 0;
    else return (
$va $vb ? -1);
}

/// run sort ///
$r = array(
    array(
        
'name' => 'name1',
        
'numbers' => array(1,3,5,7,9),
    ),
    array(
        
'name' => 'name2',
        
'numbers' => array(5,6,7,8,9),
    ),
    array(
        
'name' => 'name3',
        
'numbers' => array(1,2,3,4,5),
    ),
);
global 
$_CMP_FORMULA;
$_CMP_FORMULA 'array_sum({}["numbers"])';
usort($r"mycmp_desc");
echo 
'<pre>'print_r($r); echo '</pre>';
?>

print:
Array
(
    [0] => Array
        (
            [name] => name2
            [numbers] => Array
                (
                    [0] => 5
                    [1] => 6
                    [2] => 7
                    [3] => 8
                    [4] => 9
                )

        )

    [1] => Array
        (
            [name] => name1
            [numbers] => Array
                (
                    [0] => 1
                    [1] => 3
                    [2] => 5
                    [3] => 7
                    [4] => 9
                )

        )

    [2] => Array
        (
            [name] => name3
            [numbers] => Array
                (
                    [0] => 1
                    [1] => 2
                    [2] => 3
                    [3] => 4
                    [4] => 5
                )

        )

)

aleczapka at gmx dot net (2006-11-14 00:13:40)

Since, so many people reused array_sorter class, I decided to put here some updated version with fixes.

<?php
//
// $Id: array_sorter.inc.php 82 2005-11-17 17:14:39Z aleczapka $
//

/**
* Handles multidimentional array sorting by a key (not recursive).
*
* @author Oliwier Ptak <aleczapka@gmail.com>
*/
class array_sorter
{
    var 
$skey false;
    var 
$sarray false;
    var 
$sasc true;
    var 
$sas_object false;

    
/**
    * Constructor
    *
    * @access public
    * @param mixed $array array to sort
    * @param string $key array key to sort by
    * @param boolean $asc sort order (ascending or descending)
    */
    
function array_sorter(&$array$key$asc=true$as_object=false// {{{
    
{
        
$this->sarray $array;
        
$this->skey $key;
        
$this->sasc $asc;
        
$this->sas_object $as_object;
    } 
// }}}

    
function debug()  // {{{
    
{
        echo 
"skey: ".$this->skey."<br>";
        echo 
"sasc: ".$this->sasc."<br>";
    } 
// }}}

    /**
    * Sort method
    *
    * @access public
    * @param boolean $remap if true reindex the array to reset indexes
    */
    
function sortit($remap=true)  // {{{
    
{
        if (!
is_array($this->sarray) || !array_key_exists($this->skey, @$this->sarray[0]))
            return 
$this->sarray;

        
//$this->debug();

        
uksort($this->sarray, array($this"_as_cmp"));
        if (
$remap
        {
            
$tmp = array();
            while (list(
$id$data) = each($this->sarray))
                
$tmp[] = $data;
            return 
$tmp;
        }
        return 
$this->sarray;
    } 
// }}}

    /**
    * Custom sort function
    *
    * @access private
    * @param mixed $a an array entry
    * @param mixed $b an array entry
    */
    
function _as_cmp($a$b)  // {{{
    
{
        
//since uksort will pass here only indexes get real values from our array
        
if (!is_array($a) && !is_array($b))
        {
            
//sort objects
            
if ($this->sas_object)
            {
                
$obj_a $this->sarray[$a];
                
$obj_b $this->sarray[$b];

                
$str "\$a = \$obj_a->$this->skey;";
                
$str .= "\$b = \$obj_b->$this->skey;";
                eval(
$str);
            }
            else
            {
                
$a $this->sarray[$a][$this->skey];
                
$b $this->sarray[$b][$this->skey];
            }
        }

        
//if string - use string comparision
        
if (!ctype_digit($a) && !ctype_digit($b) && 
            !
is_int($a) && !is_int($b))
        {
            if (
$this->sasc)
                return 
strcasecmp($a$b);
            else 
                return 
strcasecmp($b$a);
        }
        else
        {
            if (
$a == $b
                return 
0;

            if (
$this->sasc)
                return (
$a $b) ? : -1;
            else
                return (
$a $b) ? -1;
        }
    }  
// }}}

}//end of class

?>

joelith at cyberone dot com dot au (2006-09-12 22:13:48)

You can use this function to sort an array of days into order. We grabbed some data from a database which comes out as array('Monday'=>34, 'Sunday'=>45... etc but the day is not in order. So use this:

<?php
function cmp($a$b){
    
$days = array('Tuesday'=>0'Wednesday'=>1'Thursday'=>2'Friday'=>3'Saturday'=>4'Sunday'=>5'Monday'=>6); 
    
// company logic dictates a week begins on a Tuesday.
    
if ($days[$a]<$days[$b]){
        return -
1;
    }else{
        return 
1;
    }
}
?>

skippy at zuavra dot net (2005-11-28 03:57:54)

As silly as it may seem, you may sometimes need a comparison function which leaves the array in the same order. It's not as trivial as returning 0 (zero) all the time, since for some reason it doesn't actually leave the values alone.
Here's a simpler and faster version of the code presented by Ignatius Reilly in an earlier note, which can be used to infer original position based on the original array:
function cmp($a, $b) {
if ($a == $b) return 0;
global $target_array_here;
static $keys;
if (!$keys) $keys = array_keys($target_array_here);
$x = array_search($a, $keys);
$y = array_search($b, $keys);
return ($x < $y ? -1 : 1);
}

Toni Soler (2005-09-28 01:51:38)

Added "sort_type" to the previous class (ascendent/descendent options)

<?php
class t_object_sorter
{
    var 
$object_array;
    var 
$sort_by;
    
    function 
_comp($a,$b)
    {
        
$key=$this->sort_by;
        if (
$this->object_array[$a]->$key == $this->object_array[$b]->$key) return 0;
        return (
$this->object_array[$a]->$key $this->object_array[$b]->$key) ? -1;
    }
    
    function 
_comp_desc($a,$b)
    {
        
$key=$this->sort_by;
        if (
$this->object_array[$a]->$key == $this->object_array[$b]->$key) return 0;
        return (
$this->object_array[$a]->$key $this->object_array[$b]->$key) ? -1;
    }
    
    function 
sort(&$object_array$sort_by$sort_type "ASC")
    {
        
$this->object_array $object_array;
        
$this->sort_by      $sort_by;
        if (
$sort_type == "DESC")
        {
            
uksort($object_array, array($this"_comp_desc"));
        }
        else
        {
            
uksort($object_array, array($this"_comp"));
        }
    }
}
?>

Commanace at gmail dot com (2005-08-27 09:38:41)

I've written a small class that will sort arrays of objects by a certain attribute:

<?php
class t_object_sorter
{
    protected 
$object_array;
    protected 
$sort_by;
    
    private function 
_comp($a,$b)
    {
        
$key=$this->sort_by;
        
debug($this->object_array[$a],__FILE__,__LINE__);
        if (
$this->object_array[$a]->$key == $this->object_array[$b]->$key) return 0;
        return (
$this->object_array[$a]->$key $this->object_array[$b]->$key) ? -1;
    }
    
    public function 
sort(&$object_array$sort_by)
    {
        
$this->object_array $object_array;
        
$this->sort_by      $sort_by;
        
uksort($object_array, array($this"_comp"));
    }
}
?>

It is used like that:

<?php
$sorter 
= new t_object_sorter;
$sorter->sort($menu->item'position');
?>

This call will sort all "item"-objects of the object "menu" by their attribute "position".

I hope this is helpfull.

Jimomighty (2005-03-19 19:30:37)

...
function cmp($a, $b)
{
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
function uksort_tree ( &$array )
{
// [PHP5] foreach ( $array as &$value )
foreach ( $array as $key => $value )
{
if ( is_array ( $value ) )
{
// [PHP5] uksort_tree ( $value );
uksort_tree ( $array[$key] );
}
}
uksort( $array, "cmp" );
}
uksort_tree( $myEntryArray );
...

aleczapka at gmx dot net (2004-12-22 04:35:31)

One remark regarding array_sorter class.
It won't work correctly with eg. dates from mysql like 20041206105350, cause you can't convert such number into integer. To fix it remove intval() from the code. If the variable is a number it will work without converting this to int anyways. Here is the fix.

<?php
....
if (
$a == $b
    return 
0;
if (
$this->sasc)
    return (
$a $b) ? : -1;
else
    return (
$a $b) ? -1;
...
?>

jg at delegation dot ca (2004-12-17 07:41:47)

To sort dates with uksort:
function datediff($a, $b) {

$a = date('U',$a);
$b = date('U',$b);
if ($a == $b) $r = 0;
else $r = ($a > $b) ? 1: -1;
return $r;
}

aleczapka at gmx dot net (2004-12-06 04:27:45)

Here is a small and very fast object to handle sorting of multidimentional arrays by a key.
<?php
/**
* Handles multidimentional array sorting by a key (not recursive)
*
* @author Oliwier Ptak <aleczapka at gmx dot net>
*/
class array_sorter
{
    var 
$skey false;
    var 
$sarray false;
    var 
$sasc true;

    
/**
    * Constructor
    *
    * @access public
    * @param mixed $array array to sort
    * @param string $key array key to sort by
    * @param boolean $asc sort order (ascending or descending)
    */
    
function array_sorter(&$array$key$asc=true)
    {
        
$this->sarray $array;
        
$this->skey $key;
        
$this->sasc $asc;
    }

    
/**
    * Sort method
    *
    * @access public
    * @param boolean $remap if true reindex the array to rewrite indexes
    */
    
function sortit($remap=true)
    {
        
$array = &$this->sarray;
        
uksort($array, array($this"_as_cmp"));
        if (
$remap)
        {
            
$tmp = array();
            while (list(
$id$data) = each($array))
                
$tmp[] = $data;
            return 
$tmp;
        }
        return 
$array;
    }

    
/**
    * Custom sort function
    *
    * @access private
    * @param mixed $a an array entry
    * @param mixed $b an array entry
    */
    
function _as_cmp($a$b)
    {
        
//since uksort will pass here only indexes get real values from our array
        
if (!is_array($a) && !is_array($b))
        {
            
$a $this->sarray[$a][$this->skey];
            
$b $this->sarray[$b][$this->skey];
        }

        
//if string - use string comparision
        
if (!ctype_digit($a) && !ctype_digit($b))
        {
            if (
$this->sasc)
                return 
strcasecmp($a$b);
            else 
                return 
strcasecmp($b$a);
        }
        else
        {
            if (
intval($a) == intval($b)) 
                return 
0;

            if (
$this->sasc)
                return (
intval($a) > intval($b)) ? -1;
            else
                return (
intval($a) > intval($b)) ? : -1;
        }
    }

}
//end of class
?>

Sample $input_array:

Array
(
    [0] => Array
        (
            [id] => 961
            [uid] => 29
            [gid] => 12
            [parent_id] => 147
            [created] => 20041206105350
            [modified] => 20041206110702
        )

    [1] => Array
        (
            [id] => 41
            [uid] => 29
            [gid] => 12
            [parent_id] => 153
            [created] => 20041025154009
            [modified] => 20041206105532
        )

    [2] => Array
        (
            [id] => 703
            [uid] => 29
            [gid] => 12
            [parent_id] => 419
            [created] => 20041025154132
            [modified] => 20041027150259
        )

Example of usage:
<?php
    
function multi_sort(&$array$key$asc=true)
    {
        
$sorter = new array_sorter($array$key$asc);
        return 
$sorter->sortit();
    }
    
//sort by parent_id in descending order
    
$my_array multi_sort($input_array"parent_id"false);
?>

The result array will be:
Array
(

    [0] => Array
        (
            [id] => 703
            [uid] => 29
            [gid] => 12
            [parent_id] => 419
            [created] => 20041025154132
            [modified] => 20041027150259
        )

    [1] => Array
        (
            [id] => 41
            [uid] => 29
            [gid] => 12
            [parent_id] => 153
            [created] => 20041025154009
            [modified] => 20041206105532
        )

    [2] => Array
        (
            [id] => 961
            [uid] => 29
            [gid] => 12
            [parent_id] => 147
            [created] => 20041206105350
            [modified] => 20041206110702
        )

fabriceb at gmx dot net (2004-07-08 06:26:23)

(about sorting an array of objects by their properties in a class - inspired by webmaster at zeroweb dot org at usort function)
I'm using classes as an abstraction for querying records in a database and use arrays of objects to store records that have an 1 to n relationship. E.g. a class "family" has family members stored as an array of objects. Each of those objects prepresents a record in a database related to the family (by it's familyId).

To identify members, I'm using their memberId as the key of the array e.g. $family->members[$memberId].
To sort the family members AFTER fetching them with the database query, you can use the functions _objSort and sortMembers which will sort the "members" array by key using it's properties (for space reasons I didn't include the methods used to open the records):
<?php
class familyMember
{
    var 
$memberId;
    var 
$familyId;
    var 
$firstName;
    var 
$age;
    var 
$hairColor;
// ...
}

class 
family
{
    var 
$familyId;
    var 
$name;
    var 
$members = array(); // array of familyMember objects
    
var $sortFields = array();
    var 
$sortDirections = array();
    
// ...
    
function _objSort(&$a, &$b$i 0)
    {
        
$field        $this->sortFields[$i];
        
$direction    $this->sortDirections[$i];
        
        
$diff strnatcmp($this->details[$a]->$field$this->details[$b]->$field) * $direction;
        if (
$diff == && isset($this->sortFields[++$i]))
        {
            
$diff $this->_objSort($a$b$i);
        }
        
        return 
$diff;
    }
    
    function 
sortMembers($sortFields)
    {
        
$i 0;
        foreach (
$sortFields as $field => $direction)
        {
            
$this->sortFields[$i] = $field;
            
$direction == "DESC" $this->sortDirections[$i] = -$this->sortDirections[$i] = 1;
            
$i++;
        }
        
        
uksort($this->details, array($this"_objSort"));
        
        
$this->sortFields = array();
        
$this->sortDirections = array();
    }
}
// open a family
$familyId 5;
$family = new family($familyId);
$family->open(); // this will also fetch all members

// sort members by 3 fields
$family->sortMembers(array("firstName" => "ASC""age" => "DESC""hairColor" => "ASC"));
// output all family members
foreach ($family->members as $member)
{
    echo 
$member->firstName." - ".$member->age." - ".$member->hairColor."<br />";
}
?>

Note that this might not be the fastest thing on earth and it hasn't been tested very much yet but I hope it's useful for someone.

webmaster at kik-it at N0SP4M dot com (2004-02-09 10:03:25)

The code below allows you to sort an array_A following array_B keys order, original keys and values remain associated.

<?

//main function
Function SortArrayAKeysLikeArrayBKeys(&$TheArrayToSort){
   uksort($TheArrayToSort,"SortArrayAKeysLikeArrayBKeys_cmp");
}

//the custom compare function
Function SortArrayAKeysLikeArrayBKeys_cmp($a,$b){
  global $TheArrayOrder;
  $PosA=KeyPosInArray($a,$TheArrayOrder);
  $PosB=KeyPosInArray($b,$TheArrayOrder);
  if ($PosA==$PosB){return 0;}else{return ($PosA > $PosB ? 1 : -1);}
}

//where is my key in my array
Function KeyPosInArray($Key,$Array){
   $i=0;
   $Pos=99999999;
   if($Array){
      foreach($Array as $K => $V){
         $i++;
         if($K==$Key){
            $Pos=$i;
            break;
         }
      }
   }
   return $Pos;
}

//the array you want to sort
$AnyArrayToSort['age']='19';
$AnyArrayToSort['ville']='rennes';
$AnyArrayToSort['website']='kik-it.com';
$AnyArrayToSort['region']='bretagne';
$AnyArrayToSort['code_postal']='35200';
$AnyArrayToSort['Nom']='Fred';

//the array with the correct keys/values order
$TheArrayOrder['Nom']='Whatever';
$TheArrayOrder['age']='Anything';
$TheArrayOrder['region']='What u want';
$TheArrayOrder['ville']='Something';
$TheArrayOrder['code_postal']='Nothing';

//before sort
print_r($AnyArrayToSort);    
echo "<br>";
//we sort
SortArrayAKeysLikeArrayBKeys($AnyArrayToSort);
echo "<br>";
//after sort
print_r($AnyArrayToSort);
?>

Will print :

Array ( [age] => 19 [ville] => rennes [website] => kik-it.com [region] => bretagne [code_postal] => 35200 [Nom] => Fred ) 

Array ( [Nom] => Fred [age] => 19 [region] => bretagne [ville] => rennes [code_postal] => 35200 [website] => kik-it.com ) 

The keys not listed in the $TheArrayOrder will appear at the end of your sorted array (only if Key Pos < 99999999 ;o)

guss at typo dot co dot il (2003-12-07 12:18:26)

ignatius dot reilly at free dot fr (2003-11-13 10:59:13)

To use a more complicated comparison function, one can use a callback to a method of an object instance.
For example the following will take an array $arr whose keys are the same as those of $reference, and reorder $arr so that the keys appear in the same order as in $reference.
class kcmp {
var $reference ;
function kcmp( $reference ) {
$this->reference = $reference ;
}
function kcompare( $a, $b ) {
$keys = array_keys( $this->reference ) ;
$position_a = array_search( $a, $keys ) ;
$position_b = array_search( $b, $keys ) ;
return $position_a < $position_b ? -1 : 1 ;
}
}
$reference = array(
"k2" => "a2",
"k3" => "a3",
"k1" => "a1"
) ;
$arr = array(
"k1" => "b1",
"k2" => "b2",
"k3" => "b3"
) ;
print_r( $arr ) ;
uksort( $arr, array( new kcmp( $reference ), "kcompare" ) ) ;
print_r( $arr ) ;

pachollini at stones dot com (2003-03-03 04:47:10)

kumar at chicagomodular (dot) com (2003-01-29 21:12:37)

The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
--necessary info from http://www.php.net/manual/en/function.usort.php if you didn't see it already

易百教程