如何使用asc和desc对多个属性对Laravel Collection进行排序?

时间:2017-11-15 23:33:04

标签: php laravel sorting collections

如果我有一个Illuminate \ Support \ Collection,如何使用asc和desc对多个属性进行排序? (这是一个简单的假设 - 根本不寻找有关查询构建的提示。)

$collection = User::all(); // not looking for User::orderBy()->get() solutions.  Read the question.
$sorting_insructions = [
    ['column'=>'first_name', 'order'=>'asc'],
    ['column'=>'date_of_birth', 'order'=>'desc'],
];
$collection->sort(function($a,$b) use ($sorting_instructions){
    // something...
});

4 个答案:

答案 0 :(得分:2)

无论是谁使用它,请记住 - 您需要根据您使用的对象集合或关联数组来调整它。应该是一个简单的调整。只需将$ a [] / $ b []内容更改为$ a->和$ b->

    public static function multiPropertySort(Collection $collection, array $sorting_instructions){

        return $collection->sort(function ($a, $b) use ($sorting_instructions){

            //stuff starts here to answer question...

            foreach($sorting_instructions as $sorting_instruction){

                $a[$sorting_instruction['column']] = (isset($a[$sorting_instruction['column']])) ? $a[$sorting_instruction['column']] : '';
                $b[$sorting_instruction['column']] = (isset($b[$sorting_instruction['column']])) ? $b[$sorting_instruction['column']] : '';

                if(empty($sorting_instruction['order']) or strtolower($sorting_instruction['order']) == 'asc'){
                    $x = ($a[$sorting_instruction['column']] <=> $b[$sorting_instruction['column']]);
                }else{
                    $x = ($b[$sorting_instruction['column']] <=> $a[$sorting_instruction['column']]);

                }

                if($x != 0){
                    return $x;
                }

            }

            return 0;

        })->values();
    }

答案 1 :(得分:1)

如果您使用Eloquent来获取集合实例,那么在查询中使用orderBy method会好得多,尤其是在列被编入索引时:

$sorting_insructions = [
    ['column'=>'first_name', 'order'=>'asc'],
    ['column'=>'date_of_birth', 'order'=>'desc'],
];

$collection = App\User::query();

foreach ($sorting_insructions as $value) {

    $collection->orderBy($value['column'], $value['order']);

}

$users = $collection->get();

编辑由于编辑的问题告诉我应该在查询构建器之外使用排序,因此我认为$sorting_insructionssortBy的顺序与$collection = App\User::all(); $sorting_insructions = [ ['column'=>'first_name', 'order'=>'asc'], ['column'=>'date_of_birth', 'order'=>'desc'], ]; for ($i = count($sorting_insructions) - 1; $i >= 0 ; $i--) { extract($sorting_insructions[i]); if ( $order === 'asc') { $collection = $collection->sortBy( $column ); } else { $collection = $collection->sortByDesc( $column ); } } 的顺序相反给出了相同的结果:

revertFocus: function() {
        var me = this,
            focusEvent = me.focusEnterEvent,
            activeElement = Ext.Element.getActiveElement(),
            focusTarget, fromComponent, reverted;

        // If we have a record of where focus arrived from, 
        //  and have not been told to avoid refocusing, 
        //  and we contain the activeElement. 
        // Then, before hiding, restore focus to what was focused before we were focused. 

        // --->>> THE IF BELOW: !me.preventRefocus <<<---

        if (focusEvent && !me.preventRefocus && me.el.contains(activeElement)) {

答案 2 :(得分:0)

public static function multiPropertySort(
    Collection $collection,
    array $rules
)
{
    return $collection->sort(
        function ($a, $b) use ($rules) {
            foreach($rules as $rule){
                $sortColumn = array_get($rule, 'column');

                array_set(
                    $a,
                    $sortColumn,
                    array_get($a, $sortColumn, '')
                );

                array_set(
                    $b,
                    $sortColumn,
                    array_get($b, $sortColumn, '')
                );

                if ($sortOrder = array_get($rule, 'order', 'asc')) {
                    $x = (array_get($a, $sortColumn) <=> array_get($b, $sortColumn));
                } else {
                    $x = (array_get($b, $sortColumn) <=> array_get($a, $sortColumn));
                }

                if ($x != 0) {
                    return $x;
                }
            }

            return 0;
        }
    );
}

让我们想象一下势在必行...

答案 3 :(得分:-1)

在问到这个问题之后,我不确定这是否是最好的方法(因为有许多循环),但这是非常简短的代码。

$sortDrives = $drives->groupBy('date')->sortBy('date');
    $lastDrive = $sortDrives->map(function ($item, $key) {
    return $item->sortBy('odometer');
})->collapse()->last();

我粘贴了我自己的例子,因为逻辑很简单,可以编辑它

<强>解释

让我们说: date1&lt; date2 odometer1&lt; odometer2&lt; odometer3

首先你转过来:

[
    0 => ['date' => date2, 'odometer' => odometer3],
    1 => ['date' => date1, 'odometer' => odometer2],
    2 => ['date' => date1, 'odometer' => odometer1],
]

分为:

[
    date2 => [
        0 => ['date' => date2, 'odometer' => odometer3]
    ],
    date1 => [
        0 => ['date' => date1, 'odometer' => odometer2],
        1 => ['date' => date1, 'odometer' => odometer1]
    ]
]

然后用新密钥对其进行排序并获取:

[
    date1 => ...
    date2 => ...
]

之后,按键#2 排序,每个数组日期键指向:

[
    date1 => [
        0 => ['date' => date1, 'odometer' => odometer1],
        1 => ['date' => date1, 'odometer' => odometer2]
    ]
    date2 => [
        0 => ['date' => date2, 'odometer' => odometer3]
    ],
]

最后你只是将所有这些数组碰撞在一起(删除日期键)并得到:

[
    0 => ['date' => date1, 'odometer' => odometer1],
    1 => ['date' => date1, 'odometer' => odometer2],
    2 => ['date' => date2, 'odometer' => odometer3]
]