Question

I have a multi-dimensional array and was able to successfully re-index the level keys (they were indexed at 1 and JSON was treating it like an object instead of an array) using array_values().

However, I need the subNavigationItems subarrays to be re-indexed as well.

This is what I currently am receiving with 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 (
    ),
  ),
)

Notice how the first nested array indexes are 4, 5, 6, and 7, and the indexes of the second one are 10, 11, and 12. I need them both to start at 0. It would also be great if the function to do this can be an infinitely-recursive function.

If you see every single item has a subNavigationItems array that could potentially be filled with more things and I would need those arrays to be re-indexed at 0 as well.

Any thoughts on how I can accomplish this?

Was it helpful?

Solution

use this

<?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;
    }

OTHER TIPS

I think this should do it:

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;
    }
}

It doesn't recurse into objects, only sub-arrays.

The child arrays are predictably placed in the subNavigationItems keyed elements, so it is unnecessary to check the data type of every element in every level.

The recursive call of array_values() to re-index keys only needs to be called upon on subNavigationItems and only if it is not empty.

The following is noticeably much cleaner and has less functional overhead than the other answers.

Code: (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)
);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top