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:
- Base case - we only have one array inside the array. We construct an object with default values from it.
- 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:
- Base case - return the default value.
- 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.