©
This document uses PHP Chinese website manual Release
(PHP 4, PHP 5, PHP 7)
uasort — 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
&$array
, callable $cmp_function
)本函数对数组排序并保持索引和单元之间的关联。
主要用于对那些单元顺序很重要的结合数组进行排序。比较函数是用户自定义的。
array
输入的数组。
cmp_function
用户自定义比较函数的例子请参考 usort() 和 uksort() 。
成功时返回 TRUE
, 或者在失败时返回 FALSE
。
Example #1 uasort() 的基本例子
<?php
// Comparison function
function cmp ( $a , $b ) {
if ( $a == $b ) {
return 0 ;
}
return ( $a < $b ) ? - 1 : 1 ;
}
// Array to be sorted
$array = array( 'a' => 4 , 'b' => 8 , 'c' => - 1 , 'd' => - 9 , 'e' => 2 , 'f' => 5 , 'g' => 3 , 'h' => - 4 );
print_r ( $array );
// Sort and print the resulting array
uasort ( $array , 'cmp' );
print_r ( $array );
?>
以上例程会输出:
Array ( [a] => 4 [b] => 8 [c] => -1 [d] => -9 [e] => 2 [f] => 5 [g] => 3 [h] => -4 ) Array ( [d] => -9 [h] => -4 [c] => -1 [e] => 2 [g] => 3 [a] => 4 [f] => 5 [b] => 8 )
[#1] php at clement dot hk [2014-03-04 16:00:58]
If you want to keep the order when two members compare as equal, use this.
<?php
function stable_uasort(&$array, $cmp_function) {
if(count($array) < 2) {
return;
}
$halfway = count($array) / 2;
$array1 = array_slice($array, 0, $halfway, TRUE);
$array2 = array_slice($array, $halfway, NULL, TRUE);
stable_uasort($array1, $cmp_function);
stable_uasort($array2, $cmp_function);
if(call_user_func($cmp_function, end($array1), reset($array2)) < 1) {
$array = $array1 + $array2;
return;
}
$array = array();
reset($array1);
reset($array2);
while(current($array1) && current($array2)) {
if(call_user_func($cmp_function, current($array1), current($array2)) < 1) {
$array[key($array1)] = current($array1);
next($array1);
} else {
$array[key($array2)] = current($array2);
next($array2);
}
}
while(current($array1)) {
$array[key($array1)] = current($array1);
next($array1);
}
while(current($array2)) {
$array[key($array2)] = current($array2);
next($array2);
}
return;
}
function cmp($a, $b) {
if($a['n'] == $b['n']) {
return 0;
}
return ($a['n'] > $b['n']) ? -1 : 1;
}
$a = $b = array(
'a' => array("l" => "A", "n" => 1),
'b' => array("l" => "B", "n" => 2),
'c' => array("l" => "C", "n" => 1),
'd' => array("l" => "D", "n" => 2),
'e' => array("l" => "E", "n" => 2),
);
uasort($a, 'cmp');
print_r($a);
stable_uasort($b, 'cmp');
print_r($b);
?>
returns
Array
(
[e] => Array
(
[l] => E
[n] => 2
)
[b] => Array
(
[l] => B
[n] => 2
)
[d] => Array
(
[l] => D
[n] => 2
)
[c] => Array
(
[l] => C
[n] => 1
)
[a] => Array
(
[l] => A
[n] => 1
)
)
Array
(
[b] => Array
(
[l] => B
[n] => 2
)
[d] => Array
(
[l] => D
[n] => 2
)
[e] => Array
(
[l] => E
[n] => 2
)
[a] => Array
(
[l] => A
[n] => 1
)
[c] => Array
(
[l] => C
[n] => 1
)
)
https://bugs.php.net/bug.php?id=53341
[#2] Anonymous [2013-08-15 22:35:37]
//this fix the problem of if any of these sort functions evaluates two members as equal then the order is undefined (the sorting is not stable).
$pos=0;
foreach($values as $k => $v)
$tosort[$k]=array($v,$pos++);
uasort($tosort,function($a, $b) {
if($a[0] != $b[0])return ($a[0] < $b[0]) ? -1 : 1;
return ($a[1] < $b[1]) ? -1 : 1;}
);
foreach($tosort as $k => $v)
$values[$k]=$v[0];
[#3] iborodikhin at gmail dot com [2012-11-22 08:32:15]
To shuffle assoc array preserving keys just do this:
<?php uasort(
$array,
function ($a, $b) {
return mt_rand(0, 1) > 0 ? 1 : -1;
}
); ?>
[#4] Said Dashuk [2011-10-11 22:33:03]
My simple and effective solution for sort multi-dimensional array by any key:
<?php
function sort_by_key ($arr,$key) {
global $key2sort;
$key2sort = $key;
uasort($arr, 'sbk');
return ($arr);
}
function sbk ($a, $b) {global $key2sort; return (strcasecmp ($a[$key2sort],$b[$key2sort]));}
?>
[#5] clem at fragment dot at [2011-08-31 04:57:52]
for a simple case insensitive compare you can use this (php >= 5.3):
<?php
$greetings = array('howdy', 'Hey', 'aloha he');
uasort($a, function($a, $b){ return strcasecmp($a, $b); });
//$a == array('aloha he', 'howdy', 'Hey');
?>
[#6] yannick dot battail at gmail dot com [2010-11-17 06:37:32]
An Example using anonymous function.
Anonymous functions make some time the code easier to understand.
<?php
$fruits = array('Orange9','Orange11','Orange10','Orange6','Orange15');
uasort ( $fruits , function ($a, $b) {
return strnatcmp($a,$b); // or other function/code
}
);
print_r($fruits);
?>
returns
Array
(
[3] => Orange6
[0] => Orange9
[2] => Orange10
[1] => Orange11
[4] => Orange15
)
[#7] magikMaker [2010-10-19 02:48:49]
a quick reminder on the syntax if you want to use uasort in a Class or Object:
<?php
// procedural:
uasort($collection, 'my_sort_function');
// Object Oriented
uasort($collection, array($this, 'mySortMethod'));
// Objet Oriented with static method
uasort($collection, array('self', 'myStaticSortMethod'));
?>
[#8] Yves [2010-10-08 00:20:34]
Took me some time to figure that out:
the user function must return an *integer*, if you return a float, you may not get the expected result.
<?php
$a = ('a' => 0.9, 'b' => 0.7, 'c' => 0.8);
function sorting($a, $b) { return $a - $b; }
// The function above will not =work, you have to
function sorting($a, $b)
{
$d = $a = $b;
return $d < 0 ? -1 : ($d > 0 ? 1 : 0);
}
?>
[#9] phire_sk [2010-10-05 14:19:46]
I tried using some of the previous built multisorts, but they weren't working as expected.
So, I made my own Class, and it seems to work wonderfully.
Here is the code:
<?php
class multiSort
{
var $key; //key in your array
//runs the sort, and returns sorted array
function run ($myarray, $key_to_sort, $type_of_sort = '')
{
$this->key = $key_to_sort;
if ($type_of_sort == 'desc')
uasort($myarray, array($this, 'myreverse_compare'));
else
uasort($myarray, array($this, 'mycompare'));
return $myarray;
}
//for ascending order
function mycompare($x, $y)
{
if ( $x[$this->key] == $y[$this->key] )
return 0;
else if ( $x[$this->key] < $y[$this->key] )
return -1;
else
return 1;
}
//for descending order
function myreverse_compare($x, $y)
{
if ( $x[$this->key] == $y[$this->key] )
return 0;
else if ( $x[$this->key] > $y[$this->key] )
return -1;
else
return 1;
}
}
?>
[#10] stephan dot hoyer at netresearch dot de [2010-07-22 05:17:42]
To sort string containing Umlauts you can use this callback function:
<?php
function sortWUmlauts($s1, $s2)
{
$search = array('?','?','?','?');
$replace = array('A','O','U','s');
return strcmp(
str_ireplace($search, $replace, $s1),
str_ireplace($search, $replace, $s2)
);
}
?>
simply call:
<?php uasort($array, 'sortWUmlauts'); ?>
[#11] paul at webtop-designs dot com [2009-11-30 13:40:07]
Just expanding on php arobase kochira period com's method:
If you are looking to sort a multi-D array by a specific column and have entries in both upper and lower case, simply drop the entries to lowercase before doing the strcmp.
<?php
$dirs = array(
array('name' => 'First Folder', 'path' => 'sompath'),
array('name' => 'second folder', 'path' => 'sompath2'),
array('name' => 'Third Folder', 'path' => 'sompath3')
);
function so($a, $b) {
return (strcmp (strtolower($a['name']), strtolower($b['name'])));
}
?>
[#12] php arobase kochira period com [2008-06-08 04:13:44]
Difference between uasort() and usort(), the missing example ...
<?php
$arr = array ( 10 => array('id' => 'dix', 'aa' => '1010'),
100 => array('id' => 'cent', 'aa' => '100100'),
2 => array('id' => 'deux', 'aa' => '22'),
7 => array('id' => 'sept', 'aa' => '77'));
// id sorting
function so ($a, $b) { return (strcmp ($a['id'],$b['id'])); }
?>
*** uasort($arr, 'so') output:
<?php Array (
[100] => Array
(
[id] => cent
[aa] => 100100
)
[2] => Array
(
[id] => deux
[aa] => 22
)
[10] => Array
(
[id] => dix
[aa] => 1010
)
[7] => Array
(
[id] => sept
[aa] => 77
))?>
*** usort($arr, 'so') output:
<?php Array (
[0] => Array
(
[id] => cent
[aa] => 100100
)
[1] => Array
(
[id] => deux
[aa] => 22
)
[2] => Array
(
[id] => dix
[aa] => 1010
)
[3] => Array
(
[id] => sept
[aa] => 77
))?>
[#13] david [__at__] castlelaing.com [2004-05-10 09:28:43]
WARNING:-Regarding remmy.cjb.net (22-Oct-2003 05:57) mutisort() function:
Sorting by floating point numbers doesn't work in the current function. Use the modified version below if you want to sort by a floating point column.
<?php
// Based on the other notes given before.
// Sorts an array (you know the kind) by key
// and by the comparison operator you prefer.
// Note that instead of most important criteron first, it's
// least important criterion first.
// The default sort order is ascending, and the default sort
// type is strnatcmp.
// function multisort($array[, $key, $order, $type]...)
function multisort($array)
{
for($i = 1; $i < func_num_args(); $i += 3)
{
$key = func_get_arg($i);
if (is_string($key)) $key = '"'.$key.'"';
$order = true;
if($i + 1 < func_num_args())
$order = func_get_arg($i + 1);
$type = 0;
if($i + 2 < func_num_args())
$type = func_get_arg($i + 2);
switch($type)
{
case 1: // Case insensitive natural.
$t = 'strcasecmp($a[' . $key . '], $b[' . $key . '])';
break;
case 2: // Numeric.
$t = '($a[' . $key . '] == $b[' . $key . ']) ? 0:(($a[' . $key . '] < $b[' . $key . ']) ? -1 : 1)';
break;
case 3: // Case sensitive string.
$t = 'strcmp($a[' . $key . '], $b[' . $key . '])';
break;
case 4: // Case insensitive string.
$t = 'strcasecmp($a[' . $key . '], $b[' . $key . '])';
break;
default: // Case sensitive natural.
$t = 'strnatcmp($a[' . $key . '], $b[' . $key . '])';
break;
}
echo $t;
usort($array, create_function('$a, $b', '; return ' . ($order ? '' : '-') . '(' . $t . ');'));
}
return $array;
}
?>
[#14] php at eden2 dot com [2003-07-17 04:36:37]
Is it just me, or are the examples below misleading, and actually demonstrating situations that would be more appropriate for usort()?
After trying to make sense of the uasort() description, it sounds like it's more for sorting a 1D array like this:
"john" => "$23.12"
"tim" => "$6.50"
"bob" => "$18.54"
and getting back:
"tim" => "$6.50"
"bob" => "$18.54"
"john" => $23.12"
(assuming, of course, that your sort function is lopping off the $ and evaluating as a number -- which would complicate the use of asort() ;)
[#15] naholyr at yahoo dot fr [2003-01-10 09:35:44]
You can sort a multidimensionnal array by any of its key with this function:
function multi_sort($array, $key)
{
$cmp_val="((\$a['$key']>\$b['$key'])?1:
((\$a['$key']==\$b['$key'])?0:-1))";
$cmp=create_function('$a, $b', "return $body;");
uasort($array, $cmp);
return $array;
}
example:
$myarray = array(
array("name"=>"kernighan", "language"=>"c"),
array("name"=>"lerdorf", "language"=>"php"),
array("name"=>"Stroustrup", "language"=>"c++"),
array("name"=>"Gosling", "language"=>"java")
);
multi_sort($myarray, "name") returns:
name=Gosling language=java
name=Kernighan language=c
name=Lerdorf language=php
name=Stroustrup language=c++
[#16] dholmes at jccc d0t net [2002-10-09 14:27:26]
Here is a little sort function that actually uses a dynamic callback for usort to do it's thing.
It assumes your data is in the form of:
$data = array(
array('ID'=>'6','LAST'=>'Holmes','FIRST'=>'Dan'),
array('ID'=>'1234','LAST'=>'Smith','FIRST'=>'Agent K'),
array('ID'=>'2','LAST'=>'Smith','FIRST'=>'Agent J'),
array('ID'=>'4','LAST'=>'Barney','FIRST'=>'Bob'));
Now, you want to sort on one or more cols, don't you?
masort($data, 'LAST,FIRST');
or
masort($data,array('FIRST','ID'));
Of course you could add a bunch to it (like numeric comparison if appropriate, desc/asc, etc) but it works for me.
function masort(&$data, $sortby){
if(is_array($sortby)){
$sortby = join(',',$sortby);
}
uasort($data,create_function('$a,$b','$skeys = split(\',\',\''.$sortby.'\');
foreach($skeys as $key){
if( ($c = strcasecmp($a[$key],$b[$key])) != 0 ){
return($c);
}
}
return($c); '));
}
Notice that I am splitting the string in the comparison function? While this is certainly slower, it was the only way I would find to "pass" and "array". If anyone has a better way, please suggest. Then inside, we (string) compare the values only moving to the next key if the values are the same...and so on, and so on.
[#17] stilgar_cpsNOSPAM at zipmail dot NOSPAMcom dot br [2001-09-05 14:30:18]
Use example:
$array[0]['Fator1']=7;
$array[0]['Fator2']="Name";
$array[1]['Fator1']=5;
$array[1]['Fator2']="Name";
$array[2]['Fator1']=7;
$array[2]['Fator2']="NameDiferente";
.....
We want to order by Fator1, then Fator2, then:
function Compare($ar1, $ar2)
{
if ($ar1['Fator1']<$ar2['Fator1'])
return -1;
else if ($ar1['Fator1']>$ar2['Fator1'])
return 1;
if ($ar1['Fator2']<$ar2['Fator2'])
return -1;
else if ($ar1['Fator2']>$ar2['Fator2'])
return 1;
return 0;
}
To sort now, we use:
uasort($array, 'Compare');