uksort

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

uksort使用用户定义的比较函数按键排序数组

描述

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

使用用户提供的比较函数来确定排序顺序,按键对 array 进行就地排序。

注意:

如果两个成员比较相等,它们将保留其原始顺序。在 PHP 8.0.0 之前,它们在排序后的数组中的相对顺序是未定义的。

注意:

将数组的内部指针重置为第一个元素。

参数

array

输入数组。

callback

比较函数必须返回小于、等于或大于零的整数,如果第一个参数分别小于、等于或大于第二个参数。

callback(mixed $a, mixed $b): int
注意

从比较函数返回非整数值,例如 float,会导致回调返回值在内部转换为 int。因此,例如 0.990.1 都会被转换为整数 0,这将把这些值比较为相等。

返回值

始终返回 true

变更日志

版本 描述
8.2.0 返回值现在是 true;之前是 bool
8.0.0 如果 callback 期望将参数按引用传递,此函数现在将发出 E_WARNING

示例

示例 #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

参见

  • usort() - 使用用户定义的比较函数按值排序数组
  • uasort() - 使用用户定义的比较函数排序数组并保持索引关联
  • 数组排序函数的比较
添加注释

用户贡献的注释 17 个注释

574
PHPUser
9 年前
[编辑注:以下评论可能是错误的]

uksort 只能在英国使用
<?php
if($country=="UK"){
uksort();
}else{
echo
"您必须住在英国才能使用 uksort().";
}
?>
9
ingo at example dot test
10 年前
使用排序规则进行排序,使变音符能够正确显示

uksort($retval, array(Collator::create( 'de_DE' ), 'compare'));
11
fabriceb at gmx dot net
20 年前
(关于按类中的属性对对象数组进行排序 - 受 webmaster at zeroweb dot org at usort 函数的启发)
我将类用作查询数据库记录的抽象,并使用对象数组来存储具有 1 对 n 关系的记录。例如,“家庭”类有一个成员数组存储家庭成员。这些对象中的每一个代表与家庭相关的数据库中的记录(通过其家庭 ID)。

为了识别成员,我使用他们的成员 ID 作为数组的键,例如 $family->members[$memberId]。
为了在使用数据库查询获取家庭成员后对它们进行排序,您可以使用 _objSort 和 sortMembers 函数,这些函数将使用其属性按键对“members”数组进行排序(出于空间原因,我没有包含用于打开记录的方法)
<?php
class familyMember
{
var
$memberId;
var
$familyId;
var
$firstName;
var
$age;
var
$hairColor;
// ...
}

class
family
{
var
$familyId;
var
$name;
var
$members = array(); // familyMember 对象数组
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 == 0 && 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] = -1 : $this->sortDirections[$i] = 1;
$i++;
}

uksort($this->details, array($this, "_objSort"));

$this->sortFields = array();
$this->sortDirections = array();
}
}
// 打开一个家庭
$familyId = 5;
$family = new family($familyId);
$family->open(); // 这将同时获取所有成员

// 按 3 个字段排序成员
$family->sortMembers(array("firstName" => "ASC", "age" => "DESC", "hairColor" => "ASC"));
// 输出所有家庭成员
foreach ($family->members as $member)
{
echo
$member->firstName." - ".$member->age." - ".$member->hairColor."<br />";
}
?>

注意,这可能不是世界上最快的,而且还没有经过太多测试,但我希望它对某些人有用。
4
mdsky at web dot de
14 年前
不区分大小写,没有自己的函数

uksort($array, "strnatcasecmp");
1
aleczapka at gmx dot net
19 年前
关于 array_sorter 类的一个说明。
它不能正确地处理例如来自 mysql 的日期,例如 20041206105350,因为你不能将这样的数字转换为整数。要修复它,请从代码中删除 intval()。如果变量是数字,它会在不将其转换为 int 的情况下也能正常工作。这是修复方法。

<?php
....
if (
$a == $b)
return
0;
if (
$this->sasc)
return (
$a > $b) ? 1 : -1;
else
return (
$a > $b) ? -1 : 1;
...
?>
3
guss at typo dot co dot il
20 年前
关于上面的递归排序函数
一般来说,任何递归都可以使用简单的迭代重新实现。在这种特定情况下,使用递归来比较字符串会产生巨大的性能影响,而一个简单的循环就足够了,而且更快、更简单。
递归只在简化代码或对概念的理解时才有效。之前的例子既没有做到这一点,特别是它在每次迭代中都做了很多重复的事情,例如分配字符顺序常量,将其重新构建为数组等等。

例如,字符串比较可以这样写
function str_compare($a,$b) {
$order="aA??bBcC&#269;&#268;..."; // 通常更长,并且没有这些 html 实体
$default = strlen($a) - strlen($b);
$minlen = strlen($a) < strlen($b) ? strlen($a) : strlen($b);
for ($i = 0; $i < $minlen; $i++) {
$pos_a=strpos($order,$a[$i]);
$pos_b=strpos($order,$b[$i]);
if ($pos_a != $pos_b)
return $pos_a - $pos_b;
}
return $default;
}

这更简单、更快。
注意,上面的函数将对 $order 中未列出的字符失效。修复它应该非常简单。
2
contacto at hardcode dot com dot ar
15 年前
需要一个不区分大小写的按键排序函数吗?我需要这个,但找不到,所以我

<?php
function insensitive_uksort($a,$b) {
return
strtolower($a)<strtolower($b);
}
uksort($arr, "insensitive_uksort");
?>
1
brian dot short at gmail dot com
15 年前
如果你需要定期按等级排序(A、A+、D- 等),这里有一个比较函数,它使用不区分大小写的方法比较字符串,除非它找到等级,在这种情况下,它会通过将 "加号" 等级放在第一位、未标记等级放在第二位、"减号" 等级放在最后一位来正确排序。

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

// 特殊代码用于等级
if (strpos( $a, "+") !== false || strpos( $b, "+") !== false ||
strpos( $a, "-") !== false || strpos( $b, "-") !== false ){

$substrA = substr($a, 0, 1);
$substrB = substr($b, 0, 1);

$modifierA = (strlen($a) == 2) ? substr($a, 1, 1) : "";
$modifierB = (strlen($b) == 2) ? substr($b, 1, 1) : "";

if (
$substrA == $substrB){
// 找出加号和减号。
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");
?>

结果: 数组
(
[A+] => 1
[A-] => 5
[B+] => 7
[B] => 4
[B-] => 4
[C+] => 13
[C] => 10
[C-] => 6
[D+] => 8
[D] => 3
[D-] => 3
[F] => 5
)
0
smcbride at msn dot com
3 年前
这对于许多人来说可能是显而易见的,但只是为了帮助那些试图在课堂上使用它的人。 在一个类中,你可以在 uksort() 中使用 self:: 作为函数前缀,它将起作用。 此外,如果它是在另一个包含的类中,你可以用类名作为前缀。

class someclass {
private function ArraySortCMPIP($a, $b) {
$a = ip2long($a);
$b = ip2long($b);

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

// 输出
public function PrintResults() {
uksort($this->someIPAddressArray, 'self::ArraySortCMPIP');
print_r($this->someIPAddressArray);
}
}
1
jg at delegation dot ca
19 年前
使用 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;
}
0
DimeCadmium
6 年前
不要使用 uksort($array, "strnatcasecmp"); ... 使用 ksort($array, SORT_NATURAL|SORT_FLAG_CASE);
0
Jimomighty
19 年前
...

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

...
0
aleczapka at gmx dot net
19 年前
这是一个用于处理按键排序多维数组的小而快速的类。
<?php
/**
* 处理多维数组的排序,按键值排序(非递归)
*
* @author Oliwier Ptak <aleczapka at gmx dot net>
*/
class array_sorter
{
var
$skey = false;
var
$sarray = false;
var
$sasc = true;

/**
* 构造函数
*
* @access public
* @param mixed $array 要排序的数组
* @param string $key 要排序的数组键
* @param boolean $asc 排序顺序(升序或降序)
*/
function array_sorter(&$array, $key, $asc=true)
{
$this->sarray = $array;
$this->skey = $key;
$this->sasc = $asc;
}

/**
* 排序方法
*
* @access public
* @param boolean $remap 如果为 true,重新索引数组以重写索引
*/
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;
}

/**
* 自定义排序函数
*
* @access private
* @param mixed $a 数组条目
* @param mixed $b 数组条目
*/
function _as_cmp($a, $b)
{
//由于 uksort 仅传递索引,因此从我们的数组中获取实际值
if (!is_array($a) && !is_array($b))
{
$a = $this->sarray[$a][$this->skey];
$b = $this->sarray[$b][$this->skey];
}

//如果为字符串 - 使用字符串比较
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 : 1;
else
return (
intval($a) > intval($b)) ? 1 : -1;
}
}

}
//结束类
?>

示例 $input_array

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

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

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

使用示例
<?php
function multi_sort(&$array, $key, $asc=true)
{
$sorter = new array_sorter($array, $key, $asc);
return
$sorter->sortit();
}
//按 parent_id 降序排序
$my_array = multi_sort($input_array, "parent_id", false);
?>

结果数组将是
数组
(

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

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

[2] => 数组
(
[id] => 961
[uid] => 29
[gid] => 12
[parent_id] => 147
[created] => 20041206105350
[modified] => 20041206110702
)
0
webmaster at kik-it at N0SP4M dot com
20 年前
以下代码允许您按照 array_B 键的顺序对 array_A 进行排序,原始键和值保持关联。

<?

//主函数
函数 SortArrayAKeysLikeArrayBKeys(&$TheArrayToSort){
uksort($TheArrayToSort,"SortArrayAKeysLikeArrayBKeys_cmp");
}

//自定义比较函数
函数 SortArrayAKeysLikeArrayBKeys_cmp($a,$b){
全局 $TheArrayOrder;
$PosA=KeyPosInArray($a,$TheArrayOrder);
$PosB=KeyPosInArray($b,$TheArrayOrder);
如果 ($PosA==$PosB){返回 0;}否则{返回 ($PosA > $PosB ? 1 : -1);}
}

//我的键在我的数组中的位置
函数 KeyPosInArray($Key,$Array){
$i=0;
$Pos=99999999;
如果($Array){
foreach($Array as $K => $V){
$i++;
如果($K==$Key){
$Pos=$i;
中断;
}
}
}
返回 $Pos;
}

//要排序的数组
$AnyArrayToSort['age']='19';
$AnyArrayToSort['ville']='rennes';
$AnyArrayToSort['website']='kik-it.com';
$AnyArrayToSort['region']='bretagne';
$AnyArrayToSort['code_postal']='35200';
$AnyArrayToSort['Nom']='Fred';

//具有正确键/值顺序的数组
$TheArrayOrder['Nom']='Whatever';
$TheArrayOrder['age']='Anything';
$TheArrayOrder['region']='What u want';
$TheArrayOrder['ville']='Something';
$TheArrayOrder['code_postal']='Nothing';

//排序前
print_r($AnyArrayToSort);
echo "<br>";
//我们排序
SortArrayAKeysLikeArrayBKeys($AnyArrayToSort);
echo "<br>";
//排序后
print_r($AnyArrayToSort);
?>

将打印

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

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

在 $TheArrayOrder 中未列出的键将出现在排序后的数组末尾(仅当键位置 < 99999999 时;o)
0
ignatius dot reilly at free dot fr
20 年前
要使用更复杂的比较函数,可以使用回调函数来调用对象实例的方法。
例如,以下代码将获取一个数组 $arr,其键与 $reference 的键相同,并重新排序 $arr,以便键的顺序与 $reference 中的顺序相同。

类 kcmp {
var $reference ;
函数 kcmp( $reference ) {
$this->reference = $reference ;
}
函数 kcompare( $a, $b ) {
$keys = array_keys( $this->reference ) ;
$position_a = array_search( $a, $keys ) ;
$position_b = array_search( $b, $keys ) ;
返回 $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 ) ;
-1
andi at example dot com
8 年前
我需要能够对包含数字的字符串进行排序,例如:

"插槽 1 名称"
"插槽 2 名称"
"插槽 10 名称"

使用普通的字符串比较,"插槽 10 名称" 将出现在 "插槽 2 名称" 之前,因此我编写了一个小函数,它将在比较字符串时考虑数字。可能需要考虑一些边缘情况。

函数 strCmpWithNumbers( $a, $b) {
//将字符串拆分成单词。
$a = explode(' ',$a);
$b = explode(' ',$b);
$loop = 0;
do {
//从每个项目中获取第一个单词
$ta = Utils::gvfa($a, $loop);
$tb = Utils::gvfa($b, $loop);

如果 (isset($ta)) {
如果 (isset($tb)) {
如果 (is_numeric($ta)) {
如果 ($ta != $tb) {
返回 $ta - $tb;
}
} 否则 {
$val = strcasecmp($ta, $tb);
如果 ($val != 0) {
返回 $val;
}
}
} 否则 {
返回 1; // a 设置但 b 未设置
}
} 否则 {
返回 isset($b);
}
$loop +=1;
} 否则 {
}
-5
返回 0; // b 设置但 a 未设置
8 年前
返回 -1; // 两者都未设置

} 否则 {

返回 -1; // a 设置但 b 未设置

}
} 否则 {
返回 1; // b 设置但 a 未设置
return 0;
}
}
如果 ($ta == $tb) {
返回 0; // 两个单词相等,继续
} 否则 {
返回 $ta - $tb;
}
}
}
});
To Top