【问题标题】:Loop recursively through multidimensional array and do something for every key value递归循环遍历多维数组并对每个键值做一些事情
【发布时间】:2019-09-25 18:07:38
【问题描述】:

我正在构建一个通用数据库播种器,其中根据给定的输入(数组)播种一些表。目前我有一个嵌套 1 级深的数组:

 $topics = [
     'Array value 1',
     'Array value 2',
     'Array key value 1' => [
          'Nested array value 1',
          'Nested array value 2',
     ],
     'Array key value 2' => [
          'Nested array value 3',
     ],
 ];

在我的播种机中,我循环浏览这个主题数组。如果主题是键,则它是父级,我需要保存其 ID 以将其分配给子级。例如:'Array key value 1'的ID需要传递给'Nested array value 1',因为它们是相连的。我现在这样做的方式是这样的:

        // Define seeders.
        $topicSeeder = new TopicTableSeeder;
        $agendaPointSeeder = new AgendaPointTableSeeder;

        // Get all the Topics and create Agenda Points.
        foreach ($topics as $key => $topic) {

            // Check if Topic is an array.
            if (is_array($topic)) {
                // If Topic is a key, it is a Parent.
                if ($key) {
                    // Topic is Parent so set parentId to NULL and save own ID. 
                    $parentAgendaPointId = NULL;

                    // Execute Topic and Agenda Point seeders. 
                    $topicId = $topicSeeder->run($organizationId, $key);
                    $parentAgendaPointId = $agendaPointSeeder->run($parentAgendaPointId);                       

                }

                // If Topic is an array but not a key, it is a Child and gets the parentId. 
                for ($i = 0; $i < count($topic); $i++) {
                    $topicId = $topicSeeder->run($organizationId, $topic[$i]);
                    $agendaPointSeeder->run($parentAgendaPointId);
                }
            } else {
                // Topic isn't an array so it should have no Parent.
                $parentAgendaPointId = NULL;
                $topicId = $topicSeeder->run($topic);
                $agendaPointSeeder->run($parentAgendaPointId);
            }
        }

问题是,当数组嵌套的层次越深时,上面代码中的 foreach 就不再起作用了。例如这个数组:

  $topics = [
     'Unnested topic',
     'Unnested topic 2',
     'Key topic' => [
          'Nested topic',
          'Nested topic 2',
     ],
     'Key topic 2' => [
           'Nested key topic' => [
               'Nested topic 3',
           ],
     ],
  ];

我怎样才能使这个递归,但当它是一个子值时仍然有能力做某事?欢迎任何想法或建议,因为我现在有点卡住了。

【问题讨论】:

  • 确切的问题是什么?您的代码似乎缺少递归调用(或者显示的代码可能不完整)。你说but remain the ability to do something when it's a child value,所以你正确地检查了is_array(),并检测到当前主题是父主题。

标签: php arrays


【解决方案1】:
function loop($topics, $organizationId) {

    $topicSeeder = new TopicTableSeeder;
    $agendaPointSeeder = new AgendaPointTableSeeder;

    foreach ($topics as $key => $topic) {

        if (is_array($topic)) {

            if ($key) {
                $parentAgendaPointId = null;
                $topicId = $topicSeeder->run($organizationId, $key);
                $parentAgendaPointId = $agendaPointSeeder->run($parentAgendaPointId);
            }

            loop($topic, $organizationId);
        }

        else {
            $parentAgendaPointId = null;
            $topicId = $topicSeeder->run($topic);
            $agendaPointSeeder->run($parentAgendaPointId);
        }
    }
}

【讨论】:

  • 我怎么知道$topic 现在是child 而不仅仅是“正常”topic?因为如果它是child,我必须使用不同的参数执行播种器。
  • 您可以添加第三个参数$child,默认值为false,并将内部调用更改为true
  • 这就像一个魅力,但如果key 也是child 怎么办?就像“嵌套的关键主题”一样,我该如何检查?
  • 您可以传递任意数量的参数。我不太清楚你的情况。如果想知道迭代的深度,可以加$depth参数,默认值0。在内部调用中,将$depth + 1 传递给此参数。如果你愿意,你也可以传递父 key
  • 例如:function loop($topics, $organizationId, $parentKey=null) {。内呼:loop($topic, $organizationId, $key);
【解决方案2】:

你可以使用这个简单的递归函数:

     function recursive($topics, $key, $level=0)
  {
      if(is_array($topics)) {
          foreach($topics as $key1 => $topic) {
              if(is_array($topic)) {
                  recursive($topic, $key1, $level+1);
              } else {
                  echo "level: $level key: $key value: $topic \n";

              }
          }
        }
  }

【讨论】:

  • 但是我现在如何从parent 获得ID?因为所有children都显示为$topic?
  • 我怎么知道$topic 现在是child 而不仅仅是“正常”topic
  • 我已经编辑了答案以获得密钥。请检查。您最初可以使用 recursive($topics, 0) 调用
  • normal 主题是什么意思? ('Unnested topic','Unnested topic 2',这两个在你的例子中?)
  • 您可以添加另一个额外的参数level 来识别嵌套级别,我认为如果嵌套级别为 0,那么这些主题是“正常”主题(如您所说:D)
【解决方案3】:

你的问题不清楚。 然而:

<?php

 $topics = [
     '1',
     '2',
     '3' => [
          '1n',
          '2n',
     ],
     '4' => [
           '1n' => [
               '1nn',
            ],
        ],
  ];

function recursion($arr){
    foreach($arr as $key => $topic){
        if(is_array($topic)){
            recursion($topic);
            echo $key . " => elements: " . count($topic) . "\n";
        }else{            
            echo $topic . "\n";
        } 
    }       

}

recursion($topics);

输出如下:

1 
2
1n
2n
3 => elements: 2
1nn
1n => elements: 1 
4 => elements: 1

1, 2, 1n and 2n 是普通话题。 3 有两个子元素(分别为 1n2n)。 1nn 是普通主题,1n 有一个孩子(1nn),4 有一个孩子(1n)。

从另一个角度来看,41n 的父亲,1nn 的父亲,31n2n 的父亲。 12 没有父亲。

所以,现在您可以知道应用递归后嵌套数组的架构以及元素是否为普通子元素。

【讨论】:

    猜你喜欢
    • 2012-05-08
    • 2021-01-18
    • 2015-07-17
    • 1970-01-01
    • 2020-10-15
    • 2020-04-06
    • 2020-01-19
    • 2014-12-29
    • 2012-08-28
    相关资源
    最近更新 更多