-3

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

$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',
)
4

1 回答 1

1

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

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

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

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

  • $result = [];
    array_walk_recursive(
        $data,
        function($v, $k) use (&$result) {
            if ($k === 'Date') {
                $result[] = $v;
            }
        }
    );
    
  • 优点:
    • 因为array_walk_recursive()遍历叶节点并且“数据”总是“标量”,所以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必须声明变量
    • 如果您、您的开发团队或您未来的开发团队不熟悉可变参数;也许只是在您的代码中写一个注释并链接到 SO 页面或 php 文档以供快速参考。

经典的嵌套 foreach 循环

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