前提
給定一個二維陣列,請根據指定的陣列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
寫一個類似mysql
的order by
的功能,其實也很簡單。