-4

What would be the best way to go about creating a multilayer json if i have an array with data like below ? The data basically comes in an array format and i am trying to create the json on the fly based on the hierarchy provided by the underscore.

  0 => 'Business Services',
  1 => 'Business Services_Consulting',
  2 => 'Business Services_Foodservice Distribution',
  3 => 'Business Services_Information Services',
  4 => 'Consumer',
  5 => 'Consumer_Consumer Discretionary',
  6 => 'Consumer_Consumer Discretionary_Apparel, Footwear & Accessories',
  7 => 'Consumer_Consumer Discretionary_Apparel, Footwear & Accessories_Activewear',
  8 => 'Consumer_Consumer Discretionary_Apparel, Footwear & Accessories_Apparel',
  9 => 'Consumer_Consumer Discretionary_Apparel, Footwear & Accessories_Footwear',
  10 => 'Consumer_Consumer Discretionary_Apparel, Footwear & Accessories_Luxury Goods',
  11 => 'Consumer_Consumer Discretionary_Broadline Retail',
  12 => 'Consumer_Consumer Discretionary_Consumer Services',
  13 => 'Consumer_Consumer Discretionary_Consumer Services_Child Care',
  14 => 'Consumer_Consumer Discretionary_Consumer Services_Fitness Services/Gyms',
  15 => 'Consumer_Consumer Discretionary_Gaming, Lodging & Leisure',
  16 => 'Consumer_Consumer Discretionary_Gaming, Lodging & Leisure_Cruise Lines',
  17 => 'Consumer_Consumer Discretionary_Gaming, Lodging & Leisure_Gaming',
  18 => 'Consumer_Consumer Discretionary_Gaming, Lodging & Leisure_Live Entertainment',
  19 => 'Consumer_Consumer Discretionary_Gaming, Lodging & Leisure_Lodging',
  20 => 'Consumer_Consumer Discretionary_Gaming, Lodging & Leisure_Online Sports Betting',
  21 => 'Consumer_Consumer Discretionary_Gaming, Lodging & Leisure_Theme Parks',
  22 => 'Consumer_Consumer Discretionary_Recreational Products',
  23 => 'Consumer_Consumer Discretionary_Recreational Products_Fitness Equipment',
  24 => 'Consumer_Consumer Discretionary_Recreational Products_Recreational Vehicles',
  25 => 'Consumer_Consumer Discretionary_Recreational Products_Sporting Goods - Recreational Products',
  26 => 'Consumer_Consumer Discretionary_Recreational Products_Toys',
  27 => 'Consumer_Consumer Discretionary_Restaurants',
  28 => 'Consumer_Consumer Discretionary_Restaurants_Casual Dining',
  29 => 'Consumer_Consumer Discretionary_Restaurants_Fast Casual',
  30 => 'Consumer_Consumer Discretionary_Restaurants_Full-Service Dining',
  31 => 'Consumer_Consumer Discretionary_Restaurants_Ghost Kitchen',
  32 => 'Consumer_Consumer Discretionary_Restaurants_QSR',
  33 => 'Consumer_Consumer Discretionary_Specialty Retail',
  34 => 'Consumer_Consumer Discretionary_Specialty Retail_Auto Retail',
  35 => 'Consumer_Consumer Discretionary_Specialty Retail_Auto Retail_Online Auto Marketplaces',
  36 => 'Consumer_Consumer Discretionary_Specialty Retail_Consumer Electronics',
  37 => 'Consumer_Consumer Discretionary_Specialty Retail_Food Retail',
  38 => 'Consumer_Consumer Discretionary_Specialty Retail_Home Furnishings',
  39 => 'Consumer_Consumer Discretionary_Specialty Retail_Home Improvement',
  40 => 'Consumer_Consumer Discretionary_Specialty Retail_Sporting Goods - Specialty Retail',
  41 => 'Consumer_Consumer Staples',
  42 => 'Consumer_Consumer Staples_Household & Personal Products',
  43 => 'Consumer_Consumer Staples_Household & Personal Products_Beauty & Cosmetics',
  44 => 'Consumer_Consumer Staples_Household & Personal Products_Household Products',
  45 => 'Consumer_Consumer Staples_Packaged Food & Beverage',
  46 => 'Consumer_Consumer Staples_Packaged Food & Beverage_Beverage',
  47 => 'Consumer_Consumer Staples_Packaged Food & Beverage_Beverage _Energy Drinks',
  48 => 'Consumer_Consumer Staples_Packaged Food & Beverage_Packaged Food',
  49 => 'Consumer_Consumer Staples_Packaged Food & Beverage_Packaged Food_Alternative Protein',
  50 => 'Consumer_Consumer Staples_Tobacco / Cannabis',
  51 => 'Consumer_Consumer Staples_Tobacco / Cannabis_Cannabis',
  52 => 'Consumer_Consumer Staples_Tobacco / Cannabis_Tobacco',

The json format would be like so ideally but for all entries:

{
  'Consumer':{
      'Consumer Discretionary':{
          'Broadline Retail':'Broadline Retail',
          'Consumer Services':{
              'Child Care':'Child Care'
           }
          'Apparel, Footwear & Accessories':{
                  'Activewear':'Activewear',
                  'Apparel':'Apparel'
           }

       }

   }
}

So far i have this code in php

$sectors = array_values($subsectorTags);

$structure=[];
$firstLevel = getByLevel(1,$sectors);
$secondLevel = getByLevel(2,$sectors,$firstLevel);
$thirdLevel = getByLevel(3,$sectors,$secondLevel);
var_export($sectors);
   

function getByLevel($level,$sectors,$prevLevel=null){
  $structure=[];
  for($i = 0 ; $i<sizeof($sectors);$i++){
    $parts = explode('_',$sectors[$i]);
    if(sizeof($parts)==$level){
      
        if($prevLevel && $level==2){
          $prevLevel[$parts[$level-2]][]=$parts[$level-1];    
       
        }else if ($level==3){
         

          // somehow here i need to implement a way to access and set the inner 
          // members of the structure with their children
          $count = 0 ;
          //$stuc = $prevLevel[$parts[$count]];
          
          while($count<$level){
           // $stuc= $stuc[$parts[$count]];
           // $count=$count+1;              
          }         
          
          //$stuc[$parts[$count]][]=$parts[$count];
        }else{
          $structure[$sectors[$i]] = [];
        }
      
            
    }  
  }
 
  return (!$prevLevel)?$structure:$prevLevel; 
}
pilchard
  • 12,414
  • 5
  • 11
  • 23
arl
  • 17
  • 3
  • Please show us the code you have written so far to achieve this – RiggsFolly May 26 '21 at 21:44
  • @RiggsFolly just did, not sure if what i have so far is the right approach, but works fine for level 1 and 2 of course, but ideally should be able to have it dynamic enough – arl May 26 '21 at 21:49
  • Does this answer your question? [Convert javascript dot notation object to nested object](https://stackoverflow.com/questions/7793811/convert-javascript-dot-notation-object-to-nested-object) – pilchard May 26 '21 at 22:04
  • @pilchard that does not account for multiple standalone children or deeper levels – arl May 26 '21 at 22:13
  • ? It handles as many levels as you pass it. – pilchard May 26 '21 at 22:21

1 Answers1

0

One way to cheat this is to use & to keep a reference to the "deepest" level that you are on while exploding on the _ character. REPL here

// Our output array
$array = [];

foreach ($data as $item) {
    // Store a reference to the "deepest" item (so far)
    $last = &$array;

    // Split on known delim and iterate over
    foreach (explode('_', $item) as $key) {
        // See next comment for what this does.
        if (!is_array($last)) {
            $last = [];
        }

        // Set a key to match the value exactly. If the value has "child" objects, the logic
        // above will take care of removing the value and replacing it with an array.
        if (!array_key_exists($key, $last)) {
            $last[$key] = $key;
        }

        // Reset our "deepest" item
        $last = &$last[$key];
    }
}

This produces:

{
    "Business Services":
    {
        "Consulting": "Consulting",
        "Foodservice Distribution": "Foodservice Distribution",
        "Information Services": "Information Services"
    },
    "Consumer":
    {
        "Consumer Discretionary":
        {
            "Apparel, Footwear & Accessories":
            {
                "Activewear": "Activewear",
                "Apparel": "Apparel",
                "Footwear": "Footwear"
            }
        }
    }
}
Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • Thanks! There might also be a shorter way using [autovivification](https://en.wikipedia.org/wiki/Autovivification#PHP), but I can't quite think through that now – Chris Haas May 26 '21 at 22:51