2

I have several arrays as the following:

[ 'businessOpenAccount', 'accountSettings1.page.js' ]
[ 'businessOpenAccount', 'accountSettings2.page.js' ]
[ 'mainTest', 'test', 'test1.page.js' ]
[ 'mainTest', 'test', 'test2.page.js' ]

My expected result is to have an object in this way:

{
  businessOpenAccount: {
    'accountSettings1.page.js': {},
    'accountSettings2.page.js': {}
  },
  mainTest: {
    test: {
      'test1.page.js': {},
      'test2.page.js': {}
    }
  }
}

So actually I want to parse the arrays and build a nested object to return from them, but being sure to check that if a property already exists (because defined from a previous array) I won't override it, but just add the new nested property in it, respecting the correct order of nesting.

I tried few approaches using reduce, reduceRight and simple forEach/for loops but I still cannot really achieve the solution I would like.

Any tips please?

This is the best way I have so far, but I override the properties cycling over multiple arrays (the example with a single array):

const relevantFilePath = ['businessOpenAccount', 'accountSettings.page.js'];
let obj = {};
relevantFilePath.forEach((el, ind) => {
  if (ind === 0) {
    obj[el] = {};
    previousEl = obj[el];
  } else {
    previousEl[el] = {};
    previousEl = previousEl[el];
  }
});
console.log(obj);

2 Answers 2

2

You could iterate the given data and reduce the object and take the last item with splitted value.

var data = [['businessOpenAccount', 'accountSettings1.page.js'], ['businessOpenAccount', 'accountSettings2.page.js'], ['mainTest', 'test', 'test1.page.js'], ['mainTest', 'test', 'test2.page.js']],
    object = {};
    
data.forEach(function (a) {
    var last = a.pop().split('.')[0];
    
    a.reduce(function (o, k) {
        return o[k] = o[k] || {};
    }, object)[last] = '';
});

console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }

ES6 with without mutating original data

var data = [['businessOpenAccount', 'accountSettings1.page.js'], ['businessOpenAccount', 'accountSettings2.page.js'], ['mainTest', 'test', 'test1.page.js'], ['mainTest', 'test', 'test2.page.js']],
    object = {};
    
data.forEach(function (a) {
     var temp = a.slice(),
         last = temp.pop().split('.')[0];
    
    temp.reduce((o, k) => o[k] = o[k] || {}, object)[last] = '';
});

console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

1 Comment

Am I rude if I kindly say that I really really love you? Thanks a million!
0

A recursive solution which would work for anykind of sub array with unlimited depth.

const a = [
    ['businessOpenAccount', 'accountSettings1.page.js'], 
    ['businessOpenAccount', 'accountSettings2.page.js'], 
    [ 'businessOpenAccount', 'test1', 
        [
            ['test2', 'test2.settings.page.js', 
                [
                     ['test2', 'test2.settings.page.js'],
                     ['test3', 'test3.settings.page.js'],
                ], 
                'test4',
            ],
            ['test3', 'test3.settings.page.js'],
        ]
    ],
    ['mainTest', 'test', 'test1.page.js'], 
    ['mainTest', 'test', 'test2.page.js'],
];

const result = {};

const traverse = (result, arr) => {
    let firstEl = arr.shift();
    if (firstEl instanceof Array) {
        if (arr.length >= 1) {
            traverseTop(result, firstEl);
            return traverse(result, arr);
        } 
        return traverseTop(result, firstEl);
    }
    firstEl = firstEl.split('.')[0];
    result[firstEl] = arr.length >= 1 ? (result[firstEl] || {}) : '';
    if (arr.length >= 1) {
        return traverse(result[firstEl], arr);
    }
    return;
};

const traverseTop = (result, arr) => {
    arr.forEach((subArr) => {
        const firstEl = subArr.shift().split('.')[0];
        result[firstEl] = result[firstEl] || {};
        traverse(result[firstEl], subArr)
    });
    return result;
};

console.log(traverseTop(result, a));

3 Comments

Upvoted another your answer which was totally correct and the best answer for the question, in order to thank you for the effort, I really appreciate it and I am really thankfully for that, but Nina's solution in this case is more elegant and the purpose of SO is to provide the best solutions for other users that in future will have a similar issue so just upvoted that one in this case. But again, thanks a million
You're right, I find the other one more elegant also :)
I have updated my code to handle nested structures. I like recursion :D

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.