【问题标题】:Recursively call array_values() to re-index variable depth menu array递归调用 array_values() 重新索引可变深度菜单数组
【发布时间】:2013-11-12 21:46:39
【问题描述】:

我有一个多维数组,并且能够使用array_values() 成功地重新索引级别键(它们的索引为 1,JSON 将其视为对象而不是数组)。

但是,我还需要重新索引 subNavigationItems 子数组。

这是我目前收到的array_values($arr)

array (
  0 => 
  array (
    'navigationMenuId' => '1',
    'parentNavigationMenuId' => '0',
    'contentId' => '1',
    'fullURL' => '/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Index',
    'navigationAnchor' => 'Home',
    'navigationOrder' => '1',
    'subNavigationItems' => 
    array (
    ),
  ),
  1 => 
  array (
    'navigationMenuId' => '2',
    'parentNavigationMenuId' => '0',
    'contentId' => '15',
    'fullURL' => '/top-nav-1/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Index',
    'navigationAnchor' => 'Top Nav 1',
    'navigationOrder' => '2',
    'subNavigationItems' => 
    array (
    ),
  ),
  2 => 
  array (
    'navigationMenuId' => '3',
    'parentNavigationMenuId' => '0',
    'contentId' => '7',
    'fullURL' => '/top-nav-2/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Index',
    'navigationAnchor' => 'Top Nav 2',
    'navigationOrder' => '3',
    'subNavigationItems' => 
    array (
      4 => 
      array (
        'navigationMenuId' => '4',
        'parentNavigationMenuId' => '3',
        'contentId' => '8',
        'fullURL' => '/top-nav-2/sub-nav-1',
        'contentSlug' => 'sub-nav-1',
        'contentAlias' => 'Sub Nav 1',
        'navigationAnchor' => 'Sub Nav 1',
        'navigationOrder' => '1',
        'subNavigationItems' => 
        array (
        ),
      ),
      5 => 
      array (
        'navigationMenuId' => '5',
        'parentNavigationMenuId' => '3',
        'contentId' => '10',
        'fullURL' => '/top-nav-2/sub-nav-2',
        'contentSlug' => 'sub-nav-2',
        'contentAlias' => 'Sub Nav 2',
        'navigationAnchor' => 'Sub Nav 2',
        'navigationOrder' => '2',
        'subNavigationItems' => 
        array (
        ),
      ),
      6 => 
      array (
        'navigationMenuId' => '6',
        'parentNavigationMenuId' => '3',
        'contentId' => '9',
        'fullURL' => '/top-nav-2/sub-nav-3',
        'contentSlug' => 'sub-nav-3',
        'contentAlias' => 'Sub Nav 3',
        'navigationAnchor' => 'Sub Nav 3',
        'navigationOrder' => '3',
        'subNavigationItems' => 
        array (
        ),
      ),
      7 => 
      array (
        'navigationMenuId' => '7',
        'parentNavigationMenuId' => '3',
        'contentId' => '11',
        'fullURL' => '/top-nav-2/sub-nav-4',
        'contentSlug' => 'sub-nav-4',
        'contentAlias' => 'Sub Nav 4',
        'navigationAnchor' => 'Sub Nav 4',
        'navigationOrder' => '4',
        'subNavigationItems' => 
        array (
        ),
      ),
    ),
  ),
  3 => 
  array (
    'navigationMenuId' => '8',
    'parentNavigationMenuId' => '0',
    'contentId' => '5',
    'fullURL' => '/top-nav-3/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Top Nav 3',
    'navigationAnchor' => 'Top Nav 3',
    'navigationOrder' => '4',
    'subNavigationItems' => 
    array (
    ),
  ),
  4 => 
  array (
    'navigationMenuId' => '9',
    'parentNavigationMenuId' => '0',
    'contentId' => '6',
    'fullURL' => '/top-nav-4/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Top Nav 4',
    'navigationAnchor' => 'Top Nav 4',
    'navigationOrder' => '5',
    'subNavigationItems' => 
    array (
      10 => 
      array (
        'navigationMenuId' => '10',
        'parentNavigationMenuId' => '9',
        'contentId' => '12',
        'fullURL' => '/top-nav-4/sub-nav-1',
        'contentSlug' => 'sub-nav-1',
        'contentAlias' => 'Sub Nav 1',
        'navigationAnchor' => 'Sub Nav 1',
        'navigationOrder' => '1',
        'subNavigationItems' => 
        array (
        ),
      ),
      11 => 
      array (
        'navigationMenuId' => '11',
        'parentNavigationMenuId' => '9',
        'contentId' => '13',
        'fullURL' => '/top-nav-4/sub-nav-2',
        'contentSlug' => 'sub-nav-2',
        'contentAlias' => 'Sub Nav 2',
        'navigationAnchor' => 'Sub Nav 2',
        'navigationOrder' => '2',
        'subNavigationItems' => 
        array (
        ),
      ),
      12 => 
      array (
        'navigationMenuId' => '12',
        'parentNavigationMenuId' => '9',
        'contentId' => '14',
        'fullURL' => '/top-nav-4/sub-nav-3',
        'contentSlug' => 'sub-nav-3',
        'contentAlias' => 'Sub Nav 3',
        'navigationAnchor' => 'Sub Nav 3',
        'navigationOrder' => '3',
        'subNavigationItems' => 
        array (
        ),
      ),
    ),
  ),
  5 => 
  array (
    'navigationMenuId' => '13',
    'parentNavigationMenuId' => '0',
    'contentId' => '4',
    'fullURL' => '/top-nav-5/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Top Nav 5',
    'navigationAnchor' => 'Top Nav 5',
    'navigationOrder' => '6',
    'subNavigationItems' => 
    array (
    ),
  ),
)

注意第一个嵌套数组索引是 4、5、6 和 7,第二个索引是 10、11 和 12。我需要它们都从 0 开始。如果执行此操作的函数可以是无限递归函数。

如果您看到每个项目都有一个 subNavigationItems 数组,该数组可能会填充更多内容,那么我也需要将这些数组重新索引为 0。

有什么想法可以做到这一点吗?

【问题讨论】:

    标签: php arrays recursion multidimensional-array reindex


    【解决方案1】:

    使用这个

    <?php 
    
        function reOrderArray($array) {
            if(! is_array($array)) {
                 return $array;
            }
            $count = 0;
            $result = array();
            foreach($array as $k => $v) {
                if(is_integer_value($k)) {
                   $result[$count] = reOrderArray($v);
                   ++$count;
                } else {
                  $result[$k] = reOrderArray($v);
                }
            }
            return $result;
        }
    
        public function is_integer_value($value) {
            if(!is_int($value)) {
                if(is_string($value) && preg_match("/^-?\d+$/i",$value)) {
                    return true;
                }
                return false;
            }
            return true;
        }
    

    【讨论】:

      【解决方案2】:

      我认为应该这样做:

      function reindex_array_recursive($array) {
          if (is_array($array)) {
              if (array_keys($array) === range(0, count($array) - 1)) { // Indexed array
                  return array_values(array_map('reindex_array_recursive', $array));
              } else { // Associative array
                  foreach ($array as $value) {
                      $value = reindex_array_recursively($value);
                  }
                  return $array;
              }
          } else {
              return $array;
          }
      }
      

      它不递归到对象,只递归到子数组。

      【讨论】:

        【解决方案3】:

        子数组可预见地放置在subNavigationItems键控元素中,因此无需检查每个级别中每个元素的数据类型。

        递归调用 array_values() 以重新索引键只需要在 subNavigationItems 上调用,并且仅当它不为空时。

        与其他答案相比,以下内容明显更简洁,功能开销更少。

        代码:(Demo)

        function reindexChildren(array $array): array {
            foreach ($array as &$item) {
                if ($item['subNavigationItems']) {
                    $item = reindexChildren($item['subNavigationItems']);
                }
            }
            return array_values($array);
        }
        
        var_export(
            reindexChildren($menu)
        );
        

        【讨论】:

        • 亲爱的 Stack Overflow,我们还在 DV 中寻找正确、解释、演示和使用最佳实践的答案吗?我们不希望研究人员找到优化的答案,对吗?更好地扭曲公众的看法,使 Stack Overflow 不再是研究人员享有盛誉的工具。
        猜你喜欢
        • 2023-03-06
        • 2013-11-14
        • 2012-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-25
        • 2018-06-30
        • 2018-03-13
        相关资源
        最近更新 更多