php 二维数组排序

前提

给定一个二维数组,请根据指定的数组key,写出最优的排序。排序条件age asc,sex desc,指定数组如下:

$arr = [
            ['id'=>1, 'age'=>1, 'sex'=>6, 'name'=>'a'],
            ['id'=>2, 'age'=>3, 'sex'=>1, 'name'=>'c'],
            ['id'=>3, 'age'=>3, 'sex'=>1, 'name'=>'b'],
            ['id'=>4, 'age'=>2, 'sex'=>1, 'name'=>'d'],
        ];

估计大家都没有什么问题,排序嘛,简单的不要不要的:

方式一:
 array_multisort(array_column($arr,'age'),SORT_ASC,array_column($arr,'sex'), SORT_DESC, $mylist);

这应该是最简单的方式了,直接使用php现成的函数,快捷的不要不要的。

方式二:
 $sort = [];
        foreach($arr as $k=>$v) {
          
            $sort['age'][$k] = $v['age'];
            $sort['sex'][$k] = $v['sex'];
        }

array_multisort($sort['age'],SORT_ASC,$sort['sex'],SORT_DESC,$mylist);

嗯,勉强看的过去,但是感觉有点不优雅。

方式三:

        $orders=['age'=>'asc','sex'=>'desc'];
        usort($arr, function($a, $b) use($orders) {
            $result = [];
            foreach ($orders as $key=>$value) {
                list($field, $sort) = [$key,$value];
                if (!(isset($a[$field]) && isset($b[$field]))) {
                    continue;
                }
                if (strcasecmp($sort, 'desc') === 0) {
                    $tmp = $a;
                    $a = $b;
                    $b = $tmp;
                }
                if (is_numeric($a[$field]) && is_numeric($b[$field]) ) {
                    $result[] = $a[$field] - $b[$field];
                } else {
                    $result[] = strcmp($a[$field], $b[$field]);
                }
            }

            return implode('', $result);
        });

三种方式都可以,都比较简单,那么问题来了。

问题

如果排序数组不是固定的呢,排序数组是动态从数据库查询出来,排序条件也不是固定的呢,那么我们肯定要封装函数,如果使用 php内置函数:
function _sort(){
......
array_multisort(...)
}

这里我们就看出问题来了,array_multisort的参数不固定啊,使用有两个方法:func_get_args()...$arg,放弃func_get_args(),因为没有办法使用。如果是自己写的函数也建议不用,因为使用func_get_args(),容易让函数看上去是不需要传递参数的。如果你在写大量代码的时候,进行缩放的时候,也很难了解这个函数参数大概细节。这是非常不方便的。所以函数如下:

function _sort( &$arr, $sorts )
        {
            $sortParams = [];
            foreach ( $sorts as $key => $v ) {
                $sortParams[] = array_column($arr, $key);
                $sortParams[] = strcasecmp($v, 'desc') === 0 ? SORT_DESC : SORT_ASC;
            }
            array_push($sortParams, $arr);
          
            array_multisort(...$sortParams);
        }
 



_sort(['age'=>'asc','name'=>'desc','sex'=>'asc']);

看是去很好对吧,但是运行才知道,没有效果,难道是array_multisort不支持...$arg,查看了手册,没看到说明,?,那就放弃自带的函数,想自己写好了:


        function arrayOrderBy(array &$arr, $order = null) {
            if (is_null($order)) {
                return $arr;
            }
            $orders = explode(',', $order);

            usort($arr, function($a, $b) use($orders) {
                $result = array();

                foreach ($orders as $value) {
                    list($field, $sort) = array_map('trim', explode(' ', trim($value)));
                    if (!(isset($a[$field]) && isset($b[$field]))) {
                        continue;
                    }
                    if (strcasecmp($sort, 'desc') === 0) {
                        $tmp = $a;
                        $a = $b;
                        $b = $tmp;
                    }
                    if (is_numeric($a[$field]) && is_numeric($b[$field]) ) {
                        $result[] = $a[$field] - $b[$field];
                    } else {
                        $result[] = strcmp($a[$field], $b[$field]);
                    }
                }


arrayOrderBy($arr, 'age asc,sex asc,name desc');

其实这就是一道面试题,大概意思让用PHP写一个类似mysqlorder by的功能,其实也很简单。

参考

https://stackoverflow.com/que...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值