Home > front end >  Collapse Multidimensional Array into Simplified Array in PHP
Collapse Multidimensional Array into Simplified Array in PHP

Time:09-20

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.

CodePudding user response:

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.

CodePudding user response:

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
)
  • Related