如何通过多个键对多维数组进行排序?

时间:2014-04-02 13:13:27

标签: php sorting multidimensional-array

我正在尝试使用多维数组执行与mySQL查询“SELECT * FROM table ORDER BY field1,field2,...”相同的操作:

$Test = array(
    array("a"=>"004", "n"=>"03"),
    array("a"=>"003", "n"=>"02"),
    array("a"=>"001", "n"=>"02"),
    array("a"=>"005", "n"=>"01"),
    array("a"=>"001", "n"=>"01"),
    array("a"=>"004", "n"=>"02"),
    array("a"=>"003", "n"=>"01"),
    array("a"=>"004", "n"=>"01")
);
function msort(&$array, $keys){
    array_reverse($keys);
    foreach($keys as $key){
        uasort($array, sortByKey);
    }
    //
    function sortByKey($A, $B){

        global $key;

        $a = $A[$key];
        $b = $B[$key];
        if($a==$b) return 0;
        return ($a < $b)? -1 : 1 ;
    }
}
//
msort($Test, array("a","n"));
//
foreach($Test as $t){
    echo('<p>'.$t["a"].'-'.$t["n"].'</p>');
}

我的理论是:如果我将多次乘法排序为最重要键的不太重要的键,我会按照mySQL查询的顺序排序。

但是php正在返回“警告:uasort()要求参数2是有效的回调函数,找不到函数'sortByKey',或者在第23行的/Library/WebServer/Documents/www/teste.array_sort.php中找到无效的函数名“(uasort line)

这是一个简单的订单功能,我缺少什么?

4 个答案:

答案 0 :(得分:6)

从根本上说,我们将使用与解释here相同的方法,我们只是使用可变数量的键来执行此操作:

/**
 * Returns a comparison function to sort by $cmp
 * over multiple keys. First argument is the comparison
 * function, all following arguments are the keys to
 * sort by.
 */
function createMultiKeyCmpFunc($cmp, $key /* , keys... */) {
    $keys = func_get_args();
    array_shift($keys);

    return function (array $a, array $b) use ($cmp, $keys) {
        return array_reduce($keys, function ($result, $key) use ($cmp, $a, $b) {
            return $result ?: call_user_func($cmp, $a[$key], $b[$key]);
        });
    };
}

usort($array, createMultiKeyCmpFunc('strcmp', 'foo', 'bar', 'baz'));
// or
usort($array, createMultiKeyCmpFunc(function ($a, $b) { return $a - $b; }, 'foo', 'bar', 'baz'));

这大约等同于SQL ORDER BY foo, bar, baz

当然,如果每个密钥都需要不同类型的比较逻辑,并且您无法对所有密钥使用通用strcmp-,那么您将返回与解释{{3}相同的代码}。

答案 1 :(得分:4)

这是我编写的一些类似代码的代码:

uasort($array,function($a,$b) {
    return strcmp($a['launch'],$b['launch'])
        ?: strcmp($a['tld'],$b['tld'])
        ?: strcmp($a['sld'],$b['sld']);
});

首先比较launch,然后是tld,然后是sld,这有点滥用负数是真实的(只有零是假的)这一事实。您应该能够轻松地根据自己的需要进行调整。

答案 2 :(得分:0)

这将完成这项工作,感谢您的贡献!

function mdsort(&$array, $keys){

    global $KeyOrder;

    $KeyOrder = $keys;
    uasort($array, cmp);    
}
function cmp(array $a, array $b) {

    global $KeyOrder;

    foreach($KeyOrder as $key){
        $res = strcmp($a[$key], $b[$key]);
        if($res!=0) break;
    }
    return $res;
}
//
mdsort($Test, array("a","n"));

这段代码有点难看,但我相信它可能会更好 - 也许是一个类来解决将数组传递给“cmp”函数的问题。但它是一个起点,您可以使用它与任意数量的键进行排序。

答案 3 :(得分:0)

PHP7.4的箭头语法消除了以前使列顺序进入[177.00547411 177.00728148 177.00435833 176.99671953 176.98440208 176.96746426 176.94598429 176.92005866 176.88980009 176.85533528 176.81680257 176.77434952] [177.00547411 177.00615453 177.00667867 177.00704644 177.00725779 177.00731269 177.00721115 177.00695318 177.00653883 177.00596817 177.00524129 177.00435833] [177.00725779 177.00727941 177.00729586 177.00730713 177.00731323 177.00731417 177.00730993 177.00730051 177.00728593 177.00726617 177.00724125 177.00721115] [177.00731323 177.00731379 177.00731417 177.00731438 177.00731443 177.0073143 177.00731399 177.00731352 177.00731288 177.00731207 177.00731108 177.00730993] [177.00731438 177.0073144 177.00731442 177.00731443 177.00731443 177.00731443 177.00731442 177.00731441 177.00731439 177.00731436 177.00731433 177.0073143 ] [177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443] [177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443 177.00731443] [177.00731443] 范围所必需的大部分代码膨胀。

代码:(Demo

usort()

我认为这是编写任务脚本的一种非常简洁的方式。您可以从$orderBy = ['a', 'n']; usort($Test, fn($a, $b) => array_map(fn($v) => $a[$v], $orderBy) <=> array_map(fn($v) => $b[$v], $orderBy) ); var_export($Test); $a作为单独的数组生成指定的列值,并在它们之间编写太空飞船运算符。

如果没有使用箭头语法,则该片段会显得更加粗大。

代码:(Demo

$b

太空船操作员将遍历相应的数据对($orderBy = ['a', 'n']; usort($Test, function($a, $b) use ($orderBy) { return array_map(function($v) use ($a){ return $a[$v]; }, $orderBy) <=> array_map(function($v) use ($b){ return $b[$v]; }, $orderBy); }); var_export($Test); [0],然后[0][1],依此类推),直到达到非零值为止评估,直到用尽比较数组。