按对象字段对对象数组进行排序

Ale*_*lex 487 php arrays sorting object

如何通过其中一个字段对这个对象数组进行排序,比如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
        )

   ....
Run Code Online (Sandbox Code Playgroud)

cam*_*aca 649

使用usort,这是一个改编自手册的例子:

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

usort($your_data, "cmp");
Run Code Online (Sandbox Code Playgroud)

从评论中导入的编辑:

如果您正在从类内部对数组进行排序,并且您的排序函数fn($a, $b) => $a->count - $b->count也在类中定义,那么使用:

usort($your_data, function($a, $b) {return strcmp($a->name, $b->name);});
Run Code Online (Sandbox Code Playgroud)

  • 这很好,但如果排序函数与调用函数在同一个类中,则应使用:usort($ your_data,array($ this,"cmp")); (91认同)
  • 在您的答案中提出[@rmooney的第一条评论](http://stackoverflow.com/questions/4282413/php-sort-array-of-objects-by-object-fields#comment27943356_4282423) (10认同)
  • @rmooney是的,但只有你在课堂上. (6认同)
  • 或者,如果您的比较函数位于您要比较的模型/对象中(我认为这是一个更简洁的设计),您必须在模型/对象中包含完整的命名空间,如下所示:uasort($ members,array("Path\to")\your\Model\Member","compareByName")); (6认同)
  • 这不会给我任何排序,只是最大的排序,其余所有我都无法排序 (2认同)
  • 一个衬里:usort($ your_data,function($ a,$ b){return strcmp($ a-> name,$ b-> name);}); (2认同)
  • @clauziere 的解决方案也适用于静态方法,在我看来,这是比较函数的正确类型。 (2认同)
  • 从 php 7.4 开始,usort($items, fn($a, $b) => strcmp($a->name, $b->name); (2认同)
  • @RobertAndrews,您可以使用 strcasecmp 而不是 strcmp:https://www.php.net/manual/en/function.strcasecmp.php (2认同)
  • 比较数字时建议使用 `return $a->count <=> $b->count;` (2认同)

小智 463

下面是使用闭包的更好方法

usort($your_data, function($a, $b)
{
    return strcmp($a->name, $b->name);
});
Run Code Online (Sandbox Code Playgroud)

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

  • 我比接受的答案更喜欢这个,因为我们可以快速定义比较功能并可以在课堂上使用 (14认同)
  • 无需繁殖以对desc进行排序.只需交换args:`strcmp($ b-> name,$ a-> name)` (12认同)
  • 如果要保留数组键,请使用`uasort()` (10认同)
  • 对于sort desc,`-1*strcmp($ a-> name,$ b-> name);` (8认同)
  • `strnatcmp` 用于像人一样订购 (2认同)
  • 您可能会遇到像我这样的情况,在这种情况下,可接受的答案比该答案更可取。例如,您可能有一个父类和一个子类。子类会覆盖使用`usort`的函数,但比较函数是相同的。使用此方法,您需要复制闭包的代码,而不是调用“ protected static”方法,您只需在父类中定义一次即可。 (2认同)

Dor*_*gal 43

如果您使用的是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')); 
Run Code Online (Sandbox Code Playgroud)


Rom*_*viv 42

如果要排序整数值:

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

// Asc sort
usort($array,function($first,$second){
    return $first->number > $second->number;
});
Run Code Online (Sandbox Code Playgroud)

用字符串更新不要忘记转换为相同的寄存器(上部或下部)

// 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);
});
Run Code Online (Sandbox Code Playgroud)


zer*_*kms 27

usort($array, 'my_sort_function');

var_dump($array);

function my_sort_function($a, $b)
{
    return $a->name < $b->name;
}
Run Code Online (Sandbox Code Playgroud)

count字段将使用相同的代码.

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

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

  • @cambraca:哦,忘了它通过引用接受数组。顺便说一句,OP 没有说他需要按哪个顺序对集合进行排序。 (2认同)
  • @Alex:为什么不在数据库中对它进行排序呢?`ORDER BY count` (2认同)

mic*_*usa 11

要对一列值进行排序,结合使用array_column()array_multisort()是一种明智的方法。 演示

array_multisort(array_column($array, 'count'), $array);
Run Code Online (Sandbox Code Playgroud)

或者仅要求usort()宇宙飞船操作员在这种情况下执行较少的迭代。演示

usort($array, fn($a, $b) => $a->count <=> $b->count);
Run Code Online (Sandbox Code Playgroud)

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

即使您可变地声明要排序的列,这两种方法都允许在不使用任何附加技术的情况下使用变量。

带变量的多排序演示

$property = 'count';
array_multisort(array_column($array, $property), $array);
Run Code Online (Sandbox Code Playgroud)

带变量的 Usort 演示

$property = 'count';
usort($array, fn($a, $b) => $a->$property <=> $b->$property);
Run Code Online (Sandbox Code Playgroud)

两个本机排序函数都通过引用进行修改,因此不要尝试通过返回值访问已排序的数组。

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

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

两种方法都能够接收多个排序规则,但因为这个问题只要求对单个列进行排序,所以该指南在这里是不合适的。

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

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


Poe*_*lex 8

您可以使用此功能(适用于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;

        });
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

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)
Run Code Online (Sandbox Code Playgroud)


Adr*_* P. 7

如果一切都失败了,这是另一种解决方案:

$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;
Run Code Online (Sandbox Code Playgroud)


Luc*_* C. 5

您可以这样使用usort

usort($array,function($first,$second){
    return strcmp($first->name, $second->name);
});
Run Code Online (Sandbox Code Playgroud)


Nic*_*enc 5

如果你想对日期进行排序

   usort($threads,function($first,$second){
        return strtotime($first->dateandtime) < strtotime($second->dateandtime);
    });
Run Code Online (Sandbox Code Playgroud)