With an array of
['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
I'd like to construct an map object that looks like:
{
'social': {
swipes: {
women: null,
men: null
}
},
'upgrade': {
premium: null
}
}
const menu = ['/social/swipes/women', '/social/likes/men', '/upgrade/premium'];
const map = {};
const addLabelToMap = (root, label) => {
if(!map[root]) map[root] = {};
if(!map[root][label]) map[root][label] = {};
}
const buildMenuMap = menu => {
menu
// make a copy of menu
// .slice returns a copy of the original array
.slice()
// convert the string to an array by splitting the /'s
// remove the first one as it's empty
// .map returns a new array
.map(item => item.split('/').splice(1))
// iterate through each array and its elements
.forEach((element) => {
let root = map[element[0]] || "";
for (let i = 1; i < element.length; i++) {
const label = element[i];
addLabelToMap(root, label)
// set root to [root][label]
//root = ?
root = root[label];
}
});
}
buildMenuMap(menu);
console.log(map);
But I'm unsure how to switch the value of root
.
What do I set root
to so that it recursively calls addLabelToMap
with
'[social]'
, 'swipes' => '[social][swipes]'
, 'women' => '[social][swipes]'
, 'men'
?
I've used root = root[element]
but it's giving an error.
Alternative solutions would be great, but I'd like to understand why this isn't working fundamentally.
This problem is about creating the object and maintaining it's state while looping through input
array and splitting string based upon /
.
This can be accomplished using Array.reduce
where we start with empty object and while looping through input
we start filling it and for last word in every string we assign the value null
to object property.
let input = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let output = input.reduce((o, d) => {
let keys = d.split('/').filter(d => d)
keys.reduce((k, v, i) => {
k[v] = (i != keys.length - 1)
? k[v] || {}
: null
return k[v]
}, o)
return o
}, {})
console.log(output)
It is as easy as:
root = root[label];
if you change your helper function to:
const addLabelToMap = (root, label) => {
if(!root[label]) root[label] = {};
}
I'd write it as:
const buildMenuMap = menus => {
const root = {};
for(const menu of menus) {
const keys = menu.split("/").slice(1);
const prop = keys.pop();
const obj = keys.reduce((curr, key) => curr[key] || (curr[key] = {}), root);
obj[prop] = null;
}
return root;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With