0

From this array:

  objNeeded = [
    {onelevel: 'first'},
    {
      onelevel: 'second',
      sublevels: [
        {onelevel: 'domain'},
        {onelevel: 'subdomain'}
      ]
    },
    {
      onelevel: 'third',
      sublevels: [
        {
          onelevel: 'fourth',
          sublevels: [
            {onelevel: 'domain'}
          ]
        }
      ]
    }
  ];

I need to obtain this object:

  objNeeded = {
    first: true,
    second: {
      domain: true,
      subdomain: true
    },
    third: {
      fourth: {
        domain: true
      }
    }
  };

It can be have more nested objects and more objects on the array.

How i can obtain this with JavaScript or Typescript?

4
  • Have you tried anything yet ? Commented May 12, 2020 at 11:27
  • @Nicolas I have tried with map, but map return an array and i want an object. Commented May 12, 2020 at 11:28
  • 2
    You might want to add that in anyways. It might help us helps you. Commented May 12, 2020 at 11:34
  • How to create a minimal reproducable example Commented May 12, 2020 at 11:39

4 Answers 4

1

You could use recursion for that. Since this is a very specific problem to your usecase, i won't bother explain it here. I've left some comment in the code though.

const objNeeded = [
    {onelevel: 'first'},
    {
      onelevel: 'second',
      sublevels: [
        {onelevel: 'domain'},
        {onelevel: 'subdomain'}
      ]
    },
    {
      onelevel: 'third',
      sublevels: [
        {
          onelevel: 'fourth',
          sublevels: [
            {onelevel: 'domain'}
          ]
        }
      ]
    }
  ];
  
  // from what i understand, the rule ares 
  // 1. if the value is a string, it becomes {[key]: true}
  // 2. if there is subLevels, we recursive build the subs arrays. 
 function recursivalySetSubLevels(elements) {
   // this is the output
   const output = {}
   // we parse every element of the array ( or sub array ) and assign them to the current oneLevels value.
   elements.forEach(element => {
    // if the element has subLevels,
    if(!!element.sublevels) {
      // we recursively build the sub object
      output[element.onelevel] = recursivalySetSubLevels(element.sublevels);
    } else {
      // otherwise, we set the key of the oneLevel to true;
      output[element.onelevel] = true;
    }
   });
   // and then return the object.
   return output;
 }
 
 console.log(recursivalySetSubLevels(objNeeded));

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

Comments

1

You could do with Array#reduce and recursive call

  1. For Array#reduce use to recreate the array to object format
  2. For recursive call used to find the inner sublevels

const objNeeded = [{onelevel: 'first'}, { onelevel: 'second', sublevels: [ {onelevel: 'domain'}, {onelevel: 'subdomain'} ] }, { onelevel: 'third', sublevels: [ { onelevel: 'fourth', sublevels: [ {onelevel: 'domain'} ] } ] } ];

const res = objNeeded.reduce((acc, {
  onelevel,
  sublevels
}) => (acc[onelevel] = sublevels ? recCall(sublevels) : true, acc), {});

function recCall(arr) {
  return Object.assign({}, ...arr.map(({
    onelevel,
    sublevels
  }) => ({
    [onelevel]: sublevels ? recCall(sublevels) : true
  })))
}

console.log(res)

Comments

1

Here is a function convertObject which can get your desired result.

for (obj of currentObj) will loop through array values and convert the object.

Object.keys(obj) will return array of all the key in the object. and .includes will check whether value passed in parameter is exists in array or not.

Inside convertObject there is a recursion call is there which will be called when current array object has sublevels.

function convertObject(currentObj) {
  // result object
  let result = {};

  // loop through array values
  for (obj of currentObj) {
    // check whethere obj has sublevels or not. If it has sublevels then call recursively.
    if (Object.keys(obj).includes("sublevels")) {
      // retrieve converted object for current object.
      result[obj.onelevel] = convertObject(obj.sublevels, result[obj.onelevel]);
    } else {
      result[obj.onelevel] = true;
    }
  }

  // return result.
  return result;
}

let objNeeded = [{onelevel: 'first'}, { onelevel: 'second', sublevels: [ {onelevel: 'domain'}, {onelevel: 'subdomain'} ] }, { onelevel: 'third', sublevels: [ { onelevel: 'fourth', sublevels: [ {onelevel: 'domain'} ] } ] } ];

console.log(convertObject(objNeeded));

Comments

1

Here is another solution:

const objectNeeded = [...];

const reducer = (acc, level) => {
  if (level.onelevel) {
    acc[level.onelevel] = level.sublevels && level.sublevels.length
      ? level.sublevels.reduce(reducer, {})
      : true;
  }
  return acc;
};

// Obtain needed object
objectNeeded = objNeeded.reduce(reducer, {});

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.