usort

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

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

描述

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

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

注意:

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

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

参数

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 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 个注释

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

当然,这适用于任何比较函数,该函数为其每个参数计算一个整数“分数”以决定哪个“更大”。
12
luke dot semerau at gmail dot com
15 年前
如果你需要在调用方法中使用 usort 和一个键,我写了这个作为工具
<?php

函数 usort_comparison($obj, $method, $key) {
$usorter = &new Usort($obj, $method, $key);
返回数组(
$usorter, "sort");
}

Usort {
函数
__construct($obj, $method, $key) {
$this->obj = $obj;
$this->method = $method;
$this->key = $key;
}
函数
sort($a, $b) {
返回
call_user_func_array(数组($this->obj, $this->method), 数组($a, $b, $this->key));
}
}

?>

<?php

需要 "util/usort.php";

Foo {
$items = 数组(FooBar(13), FooBar(2));
公共函数
sorter() {
usort($this-items, usort_comparison("Foo", "_cmp", "item"));
}

公共静态函数
_cmp($a, $b, $key) {
返回
strcasecmp($a->$key, $b->$key);
}

}

FooBar {
公共
$item;
函数
__construct($val) {
$this->item = $val;
}
}

?>

~ 一个简单的例子... 但我需要使用它,键在 switch 语句中被用来动态地选择对象的不同成员进行比较(比如,按 x 或 y 或 z 排序)
14
mkr at binarywerks dot dk
21 年前
如果你想根据另一个数组作为优先级列表来排序数组,你可以使用这个函数。

<?php
函数 listcmp($a, $b)
{
全局
$order;

循环
$order 作为 $key => $value
{
如果(
$a==$value)
{
返回
0;
退出循环;
}

如果(
$b==$value)
{
返回
1;
退出循环;
}
}
}

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

<?php
函数 DateSort($a,$b,$d="-") {
如果 (
$a == $b) {
返回
0;
否则 {
//将日期转换为日期并进行比较
列表($am,$ad,$ay)=split($d,$a);
列表(
$bm,$bd,$by)=split($d,$b);
如果 (
mktime(0,0,0,$am,$ad,$ay) < mktime(0,0,0,$bm,$bd,$by)) {
返回 -
1;
否则 {
返回
1;
}
}
}
}
?>

$d 是分隔符
5
sydney at totoche dot org
18 年前
而不是做

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

你可以这样做

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

效率更高,并且根据当前区域设置执行不区分大小写的比较。
2
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,
函数 (
$a, $b) 使用 ($order) {
返回
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。
4
inigo dot grimbergen at gmail dot com
7 年前
使用数字和空值排序,并将最小的值放在顶部
<?php
usort
($list, 函数($a, $b) {
如果(
$a == null && $b != null ) 返回 1;
如果(
$a != null && $b == null ) 返回 -1;
返回
$a > $b ? 1 : -1;
});
?>
返回
1
2
3


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);
}
?>
1
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
(减法显然不可用)

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

<?php usort($myarray,array($this,"cmp")); ?>
0
rh at 20i dot com
5 天前
一个按参考顺序对元素进行排序的排序函数。

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