返回

PHP多维数组排序:动态二级键排序详解

php

多维数组一级排序:基于动态二级键

对多维数组进行排序,特别是当排序依据不是简单的数字或字母,而是数组二级结构的动态键时,是一项常见的编程挑战。当内置的排序函数无法直接满足需求时,理解问题的本质和编写自定义排序函数是关键。

本文针对形如上述问题中呈现的,第一级索引固定(如 [0], [1]...),第二级键是需要排序依据的情况,探讨有效的解决方案。 目标是基于第二级键(例如, 20190529, 20190516)对最外层数组进行排序。

问题分析

常见的数组排序函数,例如ksort(), asort() 等,主要针对一维数组或简单键值对。 它们无法直接应用于这种二级结构的动态键,因为这些函数无法“感知”到你期望依据哪一层的键进行排序。 我们必须明确指出如何比较元素,以便数组排序算法正确地排列它们。

解决方案

有两种方法能够有效地处理此类情况:使用usort()函数和使用更高级的数据转换和排序方法。

方法一:使用usort() 函数自定义排序

PHP的usort()函数允许我们提供自定义的比较函数。这个函数接收数组中的两个元素作为输入,并通过返回一个负数、零或正数来表明它们的顺序。 为了依据二级键对我们数组排序,我们需要提取每个元素的二级键进行比较。

实现步骤:

  1. 定义一个比较函数。此函数会提取每个数组元素的第一个键 (即第二级的动态键),然后比较这两个键值。
  2. 使用usort()函数,将待排序数组和比较函数传入。

代码示例:

<?php
$array =  array(
    0 => array(
        20190529 => array(
                30 => array(
                            17 => array(
                                        3846 => 0
                                      )
                          )
                  )
    ),
    1 => array(
        20190516 => array(
            31 => array(
                    17 => array(
                             512 => 0
                         )
                 )
             )
        )
    );


function compareSecondLevelKeys($a, $b) {
    $keyA = key($a);
    $keyB = key($b);
    return $keyA <=> $keyB;
}

usort($array, 'compareSecondLevelKeys');

print_r($array);

?>

原理:

  • key($a)key($b) 用于获取传入compareSecondLevelKeys函数的数组$a$b的第一级键(也是二级结构的动态键,例如2019052920190516)。
  • <=> (太空船操作符)会根据键的数值大小进行比较,方便排序。如果 $keyA 小于 $keyB 则返回 -1,相等则返回 0,大于则返回 1,从而确保 usort() 知道如何正确地排列数组元素。

方法二:提取二级键,辅助排序

另外一种办法,是在排序前将二维数组转换成为容易排序的键值对,排序之后再恢复为原有的数组结构。

实现步骤:

  1. 遍历原数组,将其转换为 [键 => 数组值] 的新数组,键就是原来的二级键。
  2. 对新数组的键进行排序 (ksort()) 或 使用usort配合比较器,对键值进行排序。
  3. 转换排序后的数组回到原格式。

代码示例:

<?php
$array =  array(
    0 => array(
        20190529 => array(
                30 => array(
                            17 => array(
                                        3846 => 0
                                      )
                          )
                  )
    ),
    1 => array(
        20190516 => array(
            31 => array(
                    17 => array(
                             512 => 0
                         )
                 )
             )
        )
    );


$tempArray = [];
foreach ($array as $item) {
   $key = key($item);
    $tempArray[$key] = $item;
}
ksort($tempArray);

$result = [];
foreach($tempArray as $item){
   $result[] = $item;
}
print_r($result);

?>

原理:

  1. foreach循环将原始数组转化为 键 => 原始数组值的关联数组,以便利用 ksort()
  2. ksort() 基于键 (即原始的第二级动态键) 排序临时的关联数组。
  3. 最后的foreach循环将排序后的关联数组重新转化为最初的形式。

安全性提示

  • 在实际使用中,必须考虑数据类型的兼容性。上述示例假设第二级键是可比较的 (数字或可排序的字符串)。如有其他数据类型(例如时间戳),比较逻辑需要对应调整。
  • 务必注意输入数据的正确性和边界条件。

以上两种解决方案可以帮助解决 “Sort the first level of a multidimensional array by its dynamic second-level key” 的问题。每种方法都有自己的优缺点,应该根据实际的项目需要和数据特点进行选择。自定义比较函数具有更强的灵活性,而先转换后排序的方法可能在某些特定场景下更加直接。