Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flat array to multi dimensional array (JavaScript)

I have the following array:

var sampleArray = [
  "CONTAINER",
  "BODY",
  "NEWS",
  "TITLE"];

I want to have the following output:

var desiredOutput = [{
        "CONTAINER": [{
            "BODY": [{
                "NEWS": [{
                    "TITLE": []
                }]
            }]
        }]
    }];

How can I achieve this in JavaScript?

Already tried with recursive loop, but it does not work, gives me undefined.

    dataChange(sampleArray);
    function dataChange(data) {
        for (var i = 0; i < data.length; i++) {
            changeTheArray[data[i]] = data[i + 1];
            data.splice(i, 1);
            dataChange(changeTheArray[data[i]]);
        }
    }

Thanks

like image 666
andika23 Avatar asked Oct 26 '17 09:10

andika23


3 Answers

This does what you're asking for, in one line, and with no additional variables:

let desiredOutput = sampleArray.reduceRight((obj, key) => [ { [key]: obj } ], []);

The reduceRight call, starting from the right hand end of the array, progressively accumulates the current data (seeded with the initial value of []) as the value of the single key in a new object { [key] : _value_ } where that object is itself the single entry in an array [ ... ].

like image 148
Alnitak Avatar answered Oct 24 '22 02:10

Alnitak


This will do it:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = [];    // Starting element.
let current = data; // Pointer to the current element in the loop

sampleArray.forEach(key => {     // For every entry, named `key` in `sampleArray`,
    const next = [];             // New array
    current.push({[key]: next}); // Add `{key: []}` to the current array,
    current = next;              // Move the pointer to the array we just added.
});

console.log(data);

{[key]: next} is relatively new syntax. They're computed property names.

This:

const a = 'foo';
const b = {[a]: 'bar'};

Is similar to:

const a = 'foo';
const b = {};
b[a] = 'bar';

You could re-write the forEach as a one-liner:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = [];    // Starting element.
let current = data; // Pointer to the current element in the loop

sampleArray.forEach(key => current.push({[key]: current = [] }));

console.log(data);

This current.push works a little counter-intuitively:

  1. Construct a new element to push. This assigns a new value to current.
  2. Push the new element to the reference .push was called on.
    • That reference is the value of current before current = [].
like image 43
Cerbrus Avatar answered Oct 24 '22 03:10

Cerbrus


Hi i made a little demo :

var sampleArray = [
      "CONTAINER",
      "BODY",
      "NEWS",
      "TITLE"
    ], 
    generateArray = [], 
    tmp = null;

for(var i = 0; i < sampleArray.length; i++) {
  if(tmp===null){
    generateArray[sampleArray[i]] = {};
    tmp = generateArray[sampleArray[i]];
  }else{
    tmp[sampleArray[i]] = {};
    tmp = tmp[sampleArray[i]];
  }         
}

console.log(generateArray);
like image 1
Álvaro Touzón Avatar answered Oct 24 '22 02:10

Álvaro Touzón