根据Laravel中的多个条件对集合进行排序

时间:2017-01-18 19:15:08

标签: php laravel sorting collections

我正在尝试先按颜色排序然后按类型排序。

我想也许双重foreach循环可能不是答案?

以下是我到目前为止的情况。

private $color_order = [
    'white',
    'green',
    'purple',
    'blue',     
    ''
];

private $type_order = [
    'diamond',
    'square',
    'circle'
];

private function sortCards($cards, $color_order, $type_order) {
    $collection = collect($cards);

    return $collection->sortBy(function($card) use ($color_order, $type_order) {
        foreach ($type_order as $index => $type) {
            foreach ($color_order as $index => $color) {
                if ($card->card_colors == $color && str_contains($card->card_type, $type)) {
                    return $index;
                }
            }
        }
    })->values();
}

2 个答案:

答案 0 :(得分:0)

这是一个可以为您完成此操作的宏。将宏放在app/Providers/AppServiceProvider.php'boot()方法中:

use Illuminate\Support\Collection;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Collection::macro('sortByMany', function($params) {
            return $this->sortBy(function($item) use ($params) {
                $sort = '';
                foreach($params as $property => $sortOrder) {
                    $key = array_search($item->{$property}, $sortOrder);
                    $sort .= $key === false ? count($sortOrder) + 1 : $key;
                }
                return (int) $sort;
            });
        });
    }
}

然后,您可以使用排序顺序数组['objectProperty' => ['sortorder'], 'otherProp' => ['otherSortOrder']]来调用它。它将按照传递给方法的顺序对属性进行排序。在您的示例中,它将是:

private function sortCards($cards, $color_order, $type_order)
{
    return collect($cards)->sortByMany(['card_colors' => $color_order, 'card_type' => $type_order])->values();
}

答案 1 :(得分:0)

这就是我解决它的方式。我知道它会更好。

也许其他人可以提供更优雅的解决方案,如果声明不会更深入,更深入?

private function sortCards($cards, $color_order, $type_order) {
    return $cards->sort(function($a, $b) use ($color_order, $type_order) {
        $pos_a = array_search($a->card_colors, $color_order);
        $pos_b = array_search($b->card_colors, $color_order);

        if ($pos_a == $pos_b) {
            $pos_a = array_search($a->card_types, $type_order);
            $pos_b = array_search($b->card_types, $type_order);

            if ($pos_a == $pos_b) return 0;
            return $pos_a - $pos_b;
        }
        return $pos_a - $pos_b;
    });
}
相关问题