PHP Conference Japan 2024

usort

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

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

描述

usort(数组 &$array, 可调用 $callback): true

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

注意:

如果两个成员比较结果相等,则保留其原始顺序。在 PHP 8.0.0 之前,它们在已排序数组中的相对顺序是不确定的。

注意: 此函数会为 array 中的元素分配新的键。它将删除可能已分配的任何现有键,而不仅仅是重新排序键。

参数

array

输入数组。

callback

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

callback(混合 $a, 混合 $b): int
警告

从比较函数返回 *非整数* 值(例如 浮点数)将导致回调返回值内部强制转换为 整数。因此,诸如 0.990.1 之类的值都将强制转换为整数 0,这将把这些值比较为相等。

返回值

始终返回 true

变更日志

版本 描述
8.2.0 返回值现在为 true;之前为 布尔值
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

可以使用太空船运算符进一步简化内部比较。

<?php
function cmp($a, $b)
{
return
$a <=> $b;
}

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

usort($a, "cmp");

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

注意:

显然,在这个简单的例子中,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;
}

/* 这是一个静态比较函数: */
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

参见

添加注释

用户贡献的注释 11 条注释

Hayley Watson
11 年前
正如文档所说,比较函数需要返回一个整数,该整数“小于、等于或大于零”。没有要求将返回值限制为 -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;
}
});
?>

可以简化为

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

当然,这适用于任何比较函数,该函数计算其每个参数的整数“分数”以决定哪个“更大”。
luke dot semerau at gmail dot com
15年前
如果您需要在调用方法中使用 usort 和键,我将其编写为实用程序
<?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;
}
}

?>

~简单的例子……但我需要使用它的方式是键用于 switch 语句中,以动态地选择要比较的对象的不同成员(例如,按 x 或 y 或 z 排序)
mkr at binarywerks dot dk
22年前
如果要根据充当优先级列表的另一个数组对数组进行排序,可以使用此函数。

<?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);
?>
derek at luddite dot net
24年前
需要日期排序,我不知道是否可用,所以我写了一个。也许它会帮助某人

<?php
function DateSort($a,$b,$d="-") {
if (
$a == $b) {
return
0;
} else {
//将日期转换为日期并进行比较
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 是分隔符
sydney at totoche dot org
18年前
无需执行

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

您可以执行此操作

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

效率更高,并且根据当前区域设置进行不区分大小写的比较。
gus dot antoniassi at gmail dot com
5年前
这是一种基于“优先级列表”进行排序的简单方法

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

?>

这将返回

数组
(
[1] => 数组
(
[id] => 1
)

[3] => 数组
(
[id] => 3
)

[0] => 数组
(
[id] => 0
)

[2] => 数组
(
[id] => 2
)

)

请注意,如果$arr中存在$order列表中不存在的值,则需要额外的检查,因为`array_search`函数对于未定义的索引返回`FALSE`。
inigo dot grimbergen at gmail dot com
7年前
用于对数字和空值进行排序,并将最小值放在顶部
<?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;
});
?>
返回
1
2
3


andi_mclean at ntlworld dot com
12年前
我需要一个排序方法,该方法可以对字符串进行排序,但要注意任何数字,并将其作为数字进行比较。我还想忽略任何非字母数字字符。

例如:
槽位 1 示例
槽位 10 示例
槽位 2 示例

实际上应该是
槽位 1 示例
槽位 2 示例
槽位 10 示例

<?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);
}
?>
chris at candm dot org dot uk
5年前
如果有人感兴趣,以下是100000000次运行的比较时间
基于比较整数(500 和 501)
太空船运算符:4
()?: 运算符:10
减法:2

基于比较浮点数(500.1 和 501.3)(已注明注意事项)
太空船运算符:5
()?: 运算符:9
减法:3

基于比较字符串(“five”和“four”)
太空船运算符:7
()?: 运算符:17
(减法显然不可用)

注意:使用空循环进行了一次虚拟运行,并将此运行的经过时间从上述每个时间中减去,以便它们只反映比较时间。至于重要性,除非您正在进行大量的比较,其中太空船运算符是首选,否则差异微不足道。
bo at erichsen dot com
23年前
当使用usort引用类中的函数时,我已经成功使用了

<?php usort($myarray,array($this,"cmp")); ?>
rh at 20i dot com
3个月前
一个根据参考顺序排序元素的排序函数。

function sort_by_reference(array $array_to_sort, array $reference_array): array {
usort($array_to_sort, function($a, $b) use ($reference_array) {
$pos_a = array_search($a, $reference_array);
$pos_b = array_search($b, $reference_array);
return $pos_a - $pos_b;
});

return $array_to_sort;
}

// 使用示例
$reference_array = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
$array_to_sort = ["three", "one", "seven", "four", "ten"];

$sorted_array = sort_by_reference($array_to_sort, $reference_array);

// 打印结果以验证排序
print_r($sorted_array);

```
数组
(
[0] => one
[1] => three
[2] => four
[3] => seven
[4] => ten
)
```
To Top