Home > Back-end >  How to convert an array of arrays to an object in Javascript
How to convert an array of arrays to an object in Javascript

Time:11-23

I need the solution for the general case

for example

let data = [['a', 'b'],['c', 'd'],['e', 'f', 'g', 'h']];

I need this:

{
    "a": {
        "c": {
            "e": 0,
            "f": 0,
            "g": 0,
            "h": 0
        },
        "d": {
            "e": 0,
            "f": 0,
            "g": 0,
            "h": 0
        }
    },
    "b": {
        "c": {
            "e": 0,
            "f": 0,
            "g": 0,
            "h": 0
        },
        "d": {
            "e": 0,
            "f": 0,
            "g": 0,
            "h": 0
        }
    }
}

and data can be any random array of arrays... I tried a recursive approach but I get stuck with Map and .fromEntries method...

CodePudding user response:

Simple recursion:

  1. Base case - we only have one array inside the array. We construct an object with default values from it.
  2. Recursive step - we have more arrays. We build up an object and each key comes from the first array, each value is a recursive call that uses the rest of the arrays:

const buildObj = (data, defaultValue = 0) => {
  if (data.length > 1) 
    return Object.fromEntries(
      data[0].map(x => [x, buildObj(data.slice(1), defaultValue)])
    )
  
  return Object.fromEntries(
    data[0].map(x => [x, defaultValue])
  );
}

console.log(buildObj([
  ['e', 'f', 'g', 'h']
]));

console.log(buildObj([
  ['c', 'd'],
  ['e', 'f', 'g', 'h']
]));

console.log(buildObj([
  ['a', 'b'],
  ['c', 'd'],
  ['e', 'f', 'g', 'h']
]));

console.log(buildObj([
  ['a', 'b'],
  ['c', 'd'],
  ['e', 'f', 'g', 'h']
], 42)); //different default
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Can also be represented by:

  1. Base case - return the default value.
  2. Recursive step - We build up an object and each key comes from the first array, each value is a recursive call that uses the rest of the arrays.

const buildObj = (data, defaultValue = 0) => {
  if (data.length !== 0)
    return Object.fromEntries(
      data[0].map(x => [x, buildObj(data.slice(1), defaultValue)])
    );
    
  return defaultValue;
}

console.log(buildObj([
  ['e', 'f', 'g', 'h']
]));

console.log(buildObj([
  ['c', 'd'],
  ['e', 'f', 'g', 'h']
]));

console.log(buildObj([
  ['a', 'b'],
  ['c', 'd'],
  ['e', 'f', 'g', 'h']
]));

console.log(buildObj([
  ['a', 'b'],
  ['c', 'd'],
  ['e', 'f', 'g', 'h']
], 42)); //different default
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

I think this runs good. Runs recursion with step. You can change forEach to for loop, if you want.


let data = [['a', 'b'],['c', 'd'],['e', 'f', 'g', 'h']];

const arrToDict = (data) => {
    const recursive  = (depth = 0) => {
    let dict = {}
    
    if (data.length === depth   1) {
        data[depth].forEach(el => {
        dict[el] = 0
    })
    } else {
        data[depth].forEach(el => {
        dict[el] = recursive(depth 1)
        })
    }
    return dict
}
return recursive();
}

arrToDict(data)

CodePudding user response:

I have used a recursion for converting each index to object and then used Memoization for a more efficient solution

Base Case: When the index has gone out of bounds of current array Recursive Case: recurse over the next index and assign the next objectified index as a value to the current key

//store the index which is already iterated/objectified
//this is just for LESS COMPUTATION and MORE EFFICIENCY
const memoizeObjectifiedIndex = {};

let data = [['a', 'b'],['c', 'd'],['e', 'f', 'g', 'h']];

//basic recursive approach
function createObject(data,index){
  //base case, 
  //if the index is just outside the length of array, 
  //here that index=3, since array is 0 indexed and last index is 2
  if(index === data.length)   return 0;
  
  //check in memoized object if current index is already objectfied
  if(memoizeObjectifiedIndex[index]){
    //you can check the hits when this condition is true and COMPUTATION is saved
    // console.log("Found for index ", index);
    return memoizeObjectifiedIndex[index];}

  const obj={};
  data[index].forEach((key) => {
        //assign the next objectified index as value to current key
        obj[key] = createObject(data,index 1);
   })
   //store the object for current index for future use
   memoizeObjectifiedIndex[index] = obj;
   return obj;
}

console.log(createObject(data,0))
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Note: You can see better output by copying and running this code in browser console.

  • Related