按一个属性对对象数组进行排序

我如何通过它的一个字段来排序这个对象数组,比如namecount?

Array
(
[0] => stdClass Object
(
[ID] => 1
[name] => Mary Jane
[count] => 420
)


[1] => stdClass Object
(
[ID] => 2
[name] => Johnny
[count] => 234
)


[2] => stdClass Object
(
[ID] => 3
[name] => Kathy
[count] => 4354
)


....
486478 次浏览
usort($array, 'my_sort_function');


var_dump($array);


function my_sort_function($a, $b)
{
return $a->name < $b->name;
}

相同的代码将用于count字段。

更多关于usort的细节:http://ru2.php.net/usort

顺便问一下,你从哪里得到这个数组?我希望不是来自数据库?

使用的作用,这里有一个从手册改编的例子:

function cmp($a, $b) {
return strcmp($a->name, $b->name);
}


usort($your_data, "cmp");

您还可以使用任何可调用的作为第二个参数。下面是一些例子:

  • 匿名函数 (from PHP 5.3)

      usort($your_data, function($a, $b) {return strcmp($a->name, $b->name);});
    
  • 来自类内部

      usort($your_data, array($this, "cmp")); // "cmp" should be a method in the class
    
  • 箭头功能 (from PHP 7.4)

      usort($your_data, fn($a, $b) => strcmp($a->name, $b->name));
    

此外,如果您正在比较数值,fn($a, $b) => $a->count - $b->count作为“比较”;函数应该做到这一点,或者,如果你想用另一种方式做同样的事情,从PHP 7开始,你可以使用宇宙飞船操作符,像这样:fn($a, $b) => $a->count <=> $b->count

这里有一种使用闭包的更好的方式

usort($your_data, function($a, $b)
{
return strcmp($a->name, $b->name);
});

请注意,这不在PHP的文档中,但如果你使用5.3+闭包,可以提供可调用参数。

如果你正在使用PHP oop,你可能需要更改为:

public static function cmp($a, $b)
{
return strcmp($a->name, $b->name);
}


//in this case FUNCTION_NAME would be cmp
usort($your_data, array('YOUR_CLASS_NAME','FUNCTION_NAME'));

如果你需要基于本地的字符串比较,你可以使用strcoll而不是strcmp

记住,如果需要,首先使用setlocaleLC_COLLATE来设置区域信息。

  usort($your_data,function($a,$b){
setlocale (LC_COLLATE, 'pl_PL.UTF-8'); // Example of Polish language collation
return strcoll($a->name,$b->name);
});

如果你在Codeigniter内部使用这个,你可以使用以下方法:

usort($jobs, array($this->job_model, "sortJobs"));  // function inside Model
usort($jobs, array($this, "sortJobs")); // Written inside Controller.

@rmooney谢谢你的建议。这对我真的很有帮助。

如果您只需要根据一个字段进行排序,那么usort是一个不错的选择。但是,如果需要按多个字段排序,解决方案很快就会变得混乱。在这种情况下,可以使用YaLinqo库*,它为数组和对象实现类似sql的查询语法。它对所有情况都有一个漂亮的语法:

$sortedByName         = from($objects)->orderBy('$v->name');
$sortedByCount        = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');

这里,'$v->count'function ($v) { return $v->count; }的缩写(两者都可以使用)。这些方法链返回迭代器,但如果需要,可以通过在末尾添加->toArray()来获得数组。

*由我开发

这里所有答案的缺点是它们使用静态字段名,所以我写了一个OOP风格的调整版本。假设您正在使用getter方法,您可以直接使用这个类并使用字段名作为参数。也许有人会觉得它有用。

class CustomSort{


public $field = '';


public function cmp($a, $b)
{
/**
* field for order is in a class variable $field
* using getter function with naming convention getVariable() we set first letter to uppercase
* we use variable variable names - $a->{'varName'} would directly access a field
*/
return strcmp($a->{'get'.ucfirst($this->field)}(), $b->{'get'.ucfirst($this->field)}());
}


public function sortObjectArrayByField($array, $field)
{
$this->field = $field;
usort($array, array("Your\Namespace\CustomSort", "cmp"));;
return $array;
}
}

你可以使用Nspl中的排序函数:

use function \nspl\a\sorted;
use function \nspl\op\propertyGetter;
use function \nspl\op\methodCaller;


// Sort by property value
$sortedByCount = sorted($objects, propertyGetter('count'));


// Or sort by result of method call
$sortedByName = sorted($objects, methodCaller('getName'));

感谢您的启发,我还必须添加一个外部$translator参数

usort($listable_products, function($a, $b) {
global $translator;
return strcmp($a->getFullTitle($translator), $b->getFullTitle($translator));
});

你可以使用这个函数(适用于PHP版本>= 5.3):

function sortArrayByKey(&$array,$key,$string = false,$asc = true){
if($string){
usort($array,function ($a, $b) use(&$key,&$asc)
{
if($asc)    return strcmp(strtolower($a{$key}), strtolower($b{$key}));
else        return strcmp(strtolower($b{$key}), strtolower($a{$key}));
});
}else{
usort($array,function ($a, $b) use(&$key,&$asc)
{
if($a[$key] == $b{$key}){return 0;}
if($asc) return ($a{$key} < $b{$key}) ? -1 : 1;
else     return ($a{$key} > $b{$key}) ? -1 : 1;


});
}
}

例子:

sortArrayByKey($yourArray,"name",true); //String sort (ascending order)
sortArrayByKey($yourArray,"name",true,false); //String sort (descending order)
sortArrayByKey($yourArray,"id"); //number sort (ascending order)
sortArrayByKey($yourArray,"count",false,false); //number sort (descending order)

你可以使用usort,像这样:

usort($array,function($first,$second){
return strcmp($first->name, $second->name);
});

如果你想对整数值进行排序:

// Desc sort
usort($array,function($first,$second){
return $first->number < $second->number;
});


// Asc sort
usort($array,function($first,$second){
return $first->number > $second->number;
});

<强>更新 对于字符串,不要忘记转换为相同的寄存器(上或下)

// Desc sort
usort($array,function($first,$second){
return strtolower($first->text) < strtolower($second->text);
});


// Asc sort
usort($array,function($first,$second){
return strtolower($first->text) > strtolower($second->text);
});

如果一切都失败了,还有另一个解决方案:

$names = array();
foreach ($my_array as $my_object) {
$names[] = $my_object->name; //any object field
}


array_multisort($names, SORT_ASC, $my_array);


return $my_array;

如果你想对日期排序

   usort($threads,function($first,$second){
return strtotime($first->dateandtime) < strtotime($second->dateandtime);
});

一个简单的替代方法,允许您动态确定排序所基于的字段:

$order_by = 'name';
usort($your_data, function ($a, $b) use ($order_by)
{
return strcmp($a->{$order_by}, $b->{$order_by});
});

这基于闭包类,它允许匿名函数。它从PHP 5.3开始提供。

这是一个实用类

class Util
{
public static function sortArrayByName(&$arrayToSort, $meta) {
usort($arrayToSort, function($a, $b) use ($meta) {
return strcmp($a[$meta], $b[$meta]);
});
}
}

叫它:

Util::sortArrayByName($array, "array_property_name");

你可以像这样使用我们

如果你想按数字排序:

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


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


usort($a, "cmp");

或Abc char:

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

更多信息:https://www.php.net/manual/en/function.usort.php

Demodave对吃多键的参考答案

 function array_sort_by(array $arr, $keys){


if(!is_array($keys))
$keyList = explode(',', $keys);
$keyList = array_keys(array_flip($keyList)); // array_unique
$keyList = array_reverse($keyList);


$result = &$arr;
foreach ($keyList as $key) {
if(array_key_exists($key, $arr))
$result = usort($result, function($a, $b) use ($key) { return strcmp($a->{$key}, $b->{$key}); });
}
return $result;
}
$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'));

用这个……

$array_list = [
"Apple" => 2,
"Pear" => 1,
"Orange" => 5,
"Lemon" => 1,
"Strawberry" => 2,
"Banana" => 3
];


function cmp($a, $b) {
return $b - $a;
}


$ao = new ArrayObject($object);
$ao->uasort('cmp');
print_r(json_encode($ao));

再见! !

对于我来说,这是我如何按照对象字段对对象数组进行排序的:

代码:(演示)——按last_name ASC排序,然后是first_name ASC

<?php


$array = array(
(object)array(
'first_name' => 'Léa',
'last_name' => 'Weber',
),
(object)array(
'first_name' => 'Alexandre',
'last_name' => 'Dupont',
),
(object)array(
'first_name' => 'Léa',
'last_name' => 'Zotal',
),
(object)array(
'first_name' => 'Jérémie',
'last_name' => 'Hoffmann',
)
);


usort($array, function($a, $b) {
return [$a->last_name, $a->first_name]
<=>
[$b->last_name, $b->first_name];
});




var_export($array);

生产:

array (
0 =>
(object) array(
'first_name' => 'Alexandre',
'last_name' => 'Dupont',
),
1 =>
(object) array(
'first_name' => 'Jérémie',
'last_name' => 'Hoffmann',
),
2 =>
(object) array(
'first_name' => 'Léa',
'last_name' => 'Weber',
),
3 =>
(object) array(
'first_name' => 'Léa',
'last_name' => 'Zotal',
),
)
PHP7.4及以上版本的箭头语法。 飞船操作符(<=>)也就是“组合比较操作符”使多列排序超级简单;或“三向比较运算符”。

资源:https://wiki.php.net/rfc/combined-comparison-operator # EYZ0 < / p >

要对一列值进行排序,array_column()array_multisort()的组合是一种明智的方法。# EYZ2

array_multisort(array_column($array, 'count'), $array);

或者在这个场景中只使用飞船操作符调用usort()以减少迭代。# EYZ1

usort($array, fn($a, $b) => $a->count <=> $b->count);

注意,尽管计数值转换为输入数组中的字符串类型值,但这两个排序函数都将正确地按数字排序,而不是按字母顺序排序(错误地将23420放在420之前)。这是一个可靠的默认特性。

即使变量声明要排序的列,这两种方法都允许使用变量,而不需要任何添加技术。

Multisort Demo with variable

$property = 'count';
array_multisort(array_column($array, $property), $array);

Usort Demo with variable

$property = 'count';
usort($array, fn($a, $b) => $a->$property <=> $b->$property);

这两个原生排序函数都是通过引用修改的,所以不要尝试通过它们的返回值访问已排序的数组。

array_multisort()的默认排序方向是升序的,因此在两个数组参数之间显式使用SORT_ASC没有任何好处。如果需要降序排序,则在两个数组之间写入SORT_DESC(作为第二个参数)。

当自定义函数体将$a数据放在飞船操作符的左侧,$b数据放在右侧时,usort()将升序排序。如果要按降序排序,只需将$b数据写在左边,$a数据写在右边。

这两种方法都能够接收多个排序规则,但是由于这个问题只要求对单个列进行排序,因此在这里不适合使用该指导。

在排序时每次迭代都调用函数(如strcmp())的效率较低。这不再是最佳实践。使用双向比较(如><)来返回布尔结果也不是这样。usort()预计会有一个三方比较。

对于有多个规则/列/属性的数据排序,这个答案提供了很好的指导。