【问题标题】:How to sort a multidimensional array by multiple columns?如何按多列对多维数组进行排序?
【发布时间】:2014-05-13 19:19:55
【问题描述】:

我正在尝试做与 MySQL 查询相同的操作

SELECT * FROM table ORDER BY field1, field2, ...

但使用 php 和多维数组:

$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' 或 /Library/WebServer/Documents/www/teste.array_sort.php 第 23 行中的无效函数名称”(uasort 行)

这是一个简单的订单功能。我错过了什么?

【问题讨论】:

  • 也许,我去看看。
  • 参考采用了不同的方法。另外,在关闭这个不仅仅是重复的问题之前,我认为应该回答为什么代码不起作用。
  • 它不起作用,因为您按 a 排序,然后又按 b 从头开始​​排序。你不是在提炼某种东西,而是在诉诸别的东西。此外,这不是您将函数作为回调传递的方式。此外,在函数中声明函数并没有真正起作用 [就像你认为的那样]。
  • 对不起,我没有得到你的 a - b 解释,但你给了我一个线索,所以我可以在上面解决它,使用这里和参考中的所有贡献。如果你有耐心看的话,你会发现这篇文章不是重复的,我的答案是不同的。

标签: php sorting multidimensional-array usort


【解决方案1】:

从根本上说,我们将使用与 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-,那么您将返回到与 here 解释的相同代码。

【讨论】:

  • 嗯,你的答案比我的更优雅,在列表中说。但是只要你说的是同一种方法,你用了很多不同的技术来解决问题,也许我对“方法”的理解不同,但是你的回答真的是对这个论坛的一个很好的贡献。谢谢!
  • “方法相同”,如“我们将创建一个比较函数,您将使用它进行精确排序”。与您最初进行几次连续排序的方法相反。这里的答案只是演示了一种动态创建该比较函数的技术,仅此而已。 :)
【解决方案2】:

这是我写的一些代码来做类似的事情:

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

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

【讨论】:

  • 整洁!我从stackoverflow.com/questions/17364127/… 链接到它:)
  • 当然,您可以根据所需的结果使用不同的*cmp 函数(strcasecmpstrncmpstrncasecmpstrnatcmpstrnatcasecmp)。
  • 或者any比较操作,真的。 return $a['foo'] - $b['foo'] ?: $a['bar'] - $b['bar']
  • @deceze 真的!只要函数为“它们相等”返回零,就可以了。
  • 参考得到了类似的解决方案。但是使用具有无限键的功能,我们将获得更多情况的解决方案(更通用的解决方案)。这就是我放sql查询的原因,你有一个字符串中的数据库,可以在任何你需要的地方排序。
【解决方案3】:

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

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”函数的问题。但这是一个起点,您可以使用它与任意数量的键进行排序。

【讨论】:

    【解决方案4】:

    PHP7.4 的箭头语法消除了以前将列顺序带入usort() 范围所必需的大量代码。

    代码:(Demo)

    $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$b 生成指定的列值作为单独的数组,并在它们之间编写太空船运算符。

    如果没有箭头语法,sn-p 会变得更粗。

    代码:(Demo)

    $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] vs [0],然后是[1] vs [1],等等),直到它达到非零评估或直到它耗尽比较数组.

    【讨论】:

      猜你喜欢
      • 2011-03-15
      • 2013-12-09
      • 2015-06-28
      • 2011-08-31
      • 2021-07-11
      相关资源
      最近更新 更多