1

I have a multidimensional array that goes many layers deep:

 $columns=[
  'id',
  'snippet'=>[
   'publishedAt',
   'channelId',
   'channelTitle',
   'description',
   'thumbnails'=>[
    'default'=>['url','width','height'],
    'medium'=>['url','width','height'],
    'high'=>['url','width','height'],
    'standard'=>['url','width','height'],
    'maxres'=>['url','width','height']
   ],
   'tags',
   'categoryId'
  ],
  'status'=>[
   'uploadStatus',
   'privacyStatus',
   'license',
   'embeddable',
   'publicStatsViewable',
   'madeForKids'
  ],
  'statistics'=>[
   'viewCount',
   'likeCount',
   'favoriteCount',
   'commentCount'
  ]
 ];

I need to change the above array to resemble:

    [id] => 1
    [snippet_publishedAt] => 1
    [snippet_channelId] => 1
    [snippet_channelTitle] => 1
    [snippet_description] => 1
    [snippet_thumbnails_default_url] => 1
    [snippet_thumbnails_default_width] => 1
    [snippet_thumbnails_default_height] => 1
    [snippet_thumbnails_medium_url] => 1
    [snippet_thumbnails_medium_width] => 1
    [snippet_thumbnails_medium_height] => 1
    [snippet_thumbnails_high_url] => 1
    [snippet_thumbnails_high_width] => 1
    [snippet_thumbnails_high_height] => 1
    [snippet_thumbnails_standard_url] => 1
    [snippet_thumbnails_standard_width] => 1
    [snippet_thumbnails_standard_height] => 1
    [snippet_thumbnails_maxres_url] => 1
    [snippet_thumbnails_maxres_width] => 1
    [snippet_thumbnails_maxres_height] => 1
    [snippet_tags] => 1
    [snippet_categoryId] => 1
    [status_uploadStatus] => 1
    [status_privacyStatus] => 1
    [status_license] => 1
    [status_embeddable] => 1
    [status_publicStatsViewable] => 1
    [status_madeForKids] => 1
    [statistics_viewCount] => 1
    [statistics_likeCount] => 1
    [statistics_favoriteCount] => 1
    [statistics_commentCount] => 1

I've been using:

$renamed=[];
foreach($columns as $key1=>$item1){
 if(is_array($item1)){
  foreach($item1 as $key2=>$item2){
   if(is_array($item2)){
    foreach($item2 as $key3=>$item3){
     if(is_array($item3)){
      foreach($item3 as $key4=>$item4){
       if(is_array($item4)){

       }else{$renamed[$key1.'_'.$key2.'_'.$key3.'_'.$item4]=1;}
      }
     }else{$renamed[$key1.'_'.$key2.'_'.$item3]=1;}
    }
   }
   else{$renamed[$key1.'_'.$item2]=1;}
  }
 }else{$renamed[$item1]=1;}
}

print_r($renamed);

But this is limited to only a few levels. I'd like it to be infinitely able to generate a result regardless of how many levels the original array has. Is there a recursive version of my code? I've been trying to figure one out without success. My problem is, when I create a function to generate a recursive result, the return itself needs to passed on to enable the next recursion but I have no idea what to pass on to the next iteration while generating my ideal result.

2 Answers 2

1

This is doable. Something like this:

 function simplify($columns, $root = '')
 {
    $output = []; 
    $root .= ($root == '' ? '' : '-');
    foreach ($columns as $key => $value) {
        if (is_array($value)) {
            $output = array_merge($output, simplify($value, $root . $key));
        } else {
            $output[$root . $value] = 1; 
        }
    }
    return $output;
 }
 
 var_export(simplify($columns));

Here's a working example.

To answer your question: There's not much to "pass on". All that is needed is to keep track of the current "root" of an sub-array and merge all the results into one big array.

I just thought of a slight improvement:

 function simplify($columns, $root = '')
 {
    $output = []; 
    foreach ($columns as $key => $value) {
        if (is_array($value)) {
            $output = array_merge($output, simplify($value, $root . $key . '-'));
        } else {
            $output[$root . $value] = 1; 
        }
    }
    return $output;
 }

And here's a working example.

Sign up to request clarification or add additional context in comments.

Comments

1

Here's my take. Pretty much similar to other answers.


$columns = [
    'id',
    'snippet' => [
        'publishedAt',
        'channelId',
        'channelTitle',
        'description',
        'thumbnails' => [
            'default' => ['url', 'width', 'height'],
            'medium' => ['url', 'width', 'height'],
            'high' => ['url', 'width', 'height'],
            'standard' => ['url', 'width', 'height'],
            'maxres' => ['url', 'width', 'height'],
        ],
        'tags',
        'categoryId',
    ],
    'status' => [
        'uploadStatus',
        'privacyStatus',
        'license',
        'embeddable',
        'publicStatsViewable',
        'madeForKids',
    ],
    'statistics' => [
        'viewCount',
        'likeCount',
        'favoriteCount',
        'commentCount',
    ],
];

function flatten($arr, $parents = []) {
    $result = [];

    foreach ($arr as $key => $value) {
        $me = $parents;
        
        if (is_array($value)) {
            $me[] = $key;           
            $result = array_merge($result, flatten($value, $me));
        } else {
            $me[] = $value;
            $result[implode("_", $me)] = 1;
        }
    }
    return $result;
}

$result = flatten($columns);
print_r($result);

Output:

Array
(
    [id] => 1
    [snippet_publishedAt] => 1
    [snippet_channelId] => 1
    [snippet_channelTitle] => 1
    [snippet_description] => 1
    [snippet_thumbnails_default_url] => 1
    [snippet_thumbnails_default_width] => 1
    [snippet_thumbnails_default_height] => 1
    [snippet_thumbnails_medium_url] => 1
    [snippet_thumbnails_medium_width] => 1
    [snippet_thumbnails_medium_height] => 1
    [snippet_thumbnails_high_url] => 1
    [snippet_thumbnails_high_width] => 1
    [snippet_thumbnails_high_height] => 1
    [snippet_thumbnails_standard_url] => 1
    [snippet_thumbnails_standard_width] => 1
    [snippet_thumbnails_standard_height] => 1
    [snippet_thumbnails_maxres_url] => 1
    [snippet_thumbnails_maxres_width] => 1
    [snippet_thumbnails_maxres_height] => 1
    [snippet_tags] => 1
    [snippet_categoryId] => 1
    [status_uploadStatus] => 1
    [status_privacyStatus] => 1
    [status_license] => 1
    [status_embeddable] => 1
    [status_publicStatsViewable] => 1
    [status_madeForKids] => 1
    [statistics_viewCount] => 1
    [statistics_likeCount] => 1
    [statistics_favoriteCount] => 1
    [statistics_commentCount] => 1
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.