从多维数组的第三层获取数据列

Get column of data from third level of a multidimensional array

我有一个包含四级数据的多维数组。这是一个小样本:

$data = [
    [
        [
            'Date' => '2021-03-15T00:00:00.0000000+01:00',
            'Arena' => ['Id' => 181796, 'Name' => 'Motala bibliotek'],
            'Description' => null,
            'IsCanceled' => null
        ],
        [
            'Date' => '2021-03-16T00:00:00.0000000+01:00',
            'Arena' => ['Id' => 181796, 'Name' => 'Motala bibliotek'],
            'Description' => null,
            'IsCanceled' => null
        ],
        [
            'Date' => '2021-03-17T00:00:00.0000000+01:00',
            'Arena' => ['Id' => 181796, 'Name' => 'Motala bibliotek'],
            'Description' => null,
            'IsCanceled' => null
        ]
    ],
    [
        [
            'Date' => '2021-03-15T00:00:00.0000000+01:00',
            'Arena' => ['Id' => 181796, 'Name' => 'Motala bibliotek'],
            'Description' => null,
            'IsCanceled' => null
        ],
        [
            'Date' => '2021-03-16T00:00:00.0000000+01:00',
            'Arena' => ['Id' => 181796, 'Name' => 'Motala bibliotek'],
            'Description' => null,
            'IsCanceled' => null
        ]
    ]
];

我需要收集数组第三层的所有 Date 值。

我知道如何遍历顶层,但我不知道如何编写其余代码以获得更深的 Date 元素。

for($i = 0; $i < count($data); $i++) {
    echo $i;
    echo "<br>";
}

期望的输出:

array (
  0 => '2021-03-15T00:00:00.0000000+01:00',
  1 => '2021-03-16T00:00:00.0000000+01:00',
  2 => '2021-03-17T00:00:00.0000000+01:00',
  3 => '2021-03-15T00:00:00.0000000+01:00',
  4 => '2021-03-16T00:00:00.0000000+01:00',
)

有几种方法可以从多维数组的第三层提取一列数据。不同的技术会有所取舍。以下演示都将生成相同的输出。 (Demo Link)

在隔离列之前用扩展运算符消除结构的顶层

  • array_column(array_merge(...$data), 'Date')
    
  • 优点:
    • 这是最简洁的选项
    • 它不会不必要地迭代任何数据
    • array_column()不需要检查列键是否存在以避免警告
    • 它非常适合使用函数式样式的代码库 -- IOW,return 值可以立即访问,不需要声明额外的变量
  • 缺点:
    • 如果您、您的开发团队或您未来的开发团队不熟悉variadics,那么这一行不是很直观。另一方面,提高对如何扁平化阵列的认识对您的团队有好处;也许只是在您的代码中写下注释,然后 link 到 SO 页面或 php 文档以供快速参考。

递归检查叶节点键(不推荐)

  • $result = [];
    array_walk_recursive(
        $data,
        function($v, $k) use (&$result) {
            if ($k === 'Date') {
                $result[] = $v;
            }
        }
    );
    
  • 优点:
    • 因为 array_walk_recursive() 遍历叶节点并且 'Data' 始终是“标量”,所以将找到所有 Date 个元素
    • 如果级别结构发生变化,代码仍然有效,因为 array_walk_recursive 是级别无知的
  • 缺点:
    • array_walk_recursive()遍历叶节点,会访问结构中的所有标量元素,这意味着会有一些无用的处理
    • 不是很简洁并且涉及匿名函数,需要将 $result 声明为可按引用修改的变量
    • 如果 Date 的数据类型变为可迭代的,则它不再是叶节点

使用扩展运算符循环和推送元素列

  • $result = [];
    foreach ($data as $group) {
        array_push($result, ...array_column($group, 'Date'));
    }
    var_export($result);
    
  • 优点:
    • 它不是太冗长并且不涉及匿名函数(因此没有可修改的引用变量)
    • 它不会不必要地迭代任何数据
  • 缺点:
    • 它不适合函数式编程风格,因为必须声明 $result 变量
    • 如果您、您的开发团队或您未来的开发团队不熟悉variadics;也许只是在您的代码中写下注释,然后 link 到 SO 页面或 php 文档以供快速参考。

经典的嵌套 foreach 循环

  • $result = [];
    foreach ($data as $group) {
        foreach ($group as $row) {
            if (array_key_exists('Date', $row)) {
                $result[] = $row['Date'];
            }
        }
    }
    
  • 优点:
    • 对于任何经验水平的开发人员来说,可能是最多的intuitive/semantic
    • 它不会不必要地迭代任何数据
    • 它具有最小的功能开销*,因此它可能会在庞大的数据集上表现最佳(如果这是一个合理的问题,请务必进行基准测试)
  • 缺点:
    • 完全是过程式风格,需要声明一个$result变量
    • 比较冗长
  • *如果保证输入数据在所有级别上都包含 Date 元素,则 array_key_exists() 条件将不是必需的。如果不能保证它们存在,则该条件用于防止警告。