building a menu list object recursively in javascript
up vote
4
down vote
favorite
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
javascript
add a comment |
up vote
4
down vote
favorite
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
javascript
Shouldn'tmenbe in thelikesobject not theswipesobject?
– ibrahim mahrir
Nov 14 at 21:22
I've just edited it
– totalnoob
Nov 14 at 21:23
add a comment |
up vote
4
down vote
favorite
up vote
4
down vote
favorite
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
javascript
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
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);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);javascript
javascript
edited Nov 14 at 23:08
asked Nov 14 at 21:20
totalnoob
3391629
3391629
Shouldn'tmenbe in thelikesobject not theswipesobject?
– ibrahim mahrir
Nov 14 at 21:22
I've just edited it
– totalnoob
Nov 14 at 21:23
add a comment |
Shouldn'tmenbe in thelikesobject not theswipesobject?
– ibrahim mahrir
Nov 14 at 21:22
I've just edited it
– totalnoob
Nov 14 at 21:23
Shouldn't
men be in the likes object not the swipes object?– ibrahim mahrir
Nov 14 at 21:22
Shouldn't
men be in the likes object not the swipes object?– ibrahim mahrir
Nov 14 at 21:22
I've just edited it
– totalnoob
Nov 14 at 21:23
I've just edited it
– totalnoob
Nov 14 at 21:23
add a comment |
6 Answers
6
active
oldest
votes
up vote
5
down vote
accepted
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)
how does let keys = d.split('/').filter(d => d) remove the empty entries?
– totalnoob
Nov 25 at 19:23
.splitwill split the string based on '/'. So string/social/swipes/womenwill become - ['', social,swipes,women] andfilterwill then removefalsyvalues and emoty string is a falsy value
– Nitish Narang
Nov 25 at 19:25
1
.filter(d => d)represents filter onlytruthyvalue
– Nitish Narang
Nov 25 at 19:26
Falsyvalues Doc - developer.mozilla.org/en-US/docs/Glossary/Falsy
– Nitish Narang
Nov 25 at 19:27
clear and simple. thanks
– totalnoob
Nov 25 at 19:27
|
show 4 more comments
up vote
3
down vote
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;
}
it didn't work when I tried it
– totalnoob
Nov 14 at 21:26
that's awesome. can you tell me why the current code doesn't work even setting root properly?
– totalnoob
Nov 14 at 21:31
@totalnoob becauseaddLabelToMapdoes not go deeper into the map
– Jonas Wilms
Nov 14 at 21:32
when I use root = root[label], on the next loop root is undefined if I print it out
– totalnoob
Nov 14 at 21:38
add a comment |
up vote
2
down vote
Use reduce instead of map. The root will be the accumulator in this case:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
Explanation:
For each item in the menu array, we extract the parts by first getting rid of the leading '/' (using slice(1)) and then splitting by '/'.
We then remove the lastPart from this resulting array (the last part is handled separetely from the rest).
For each remaining part in the parts array, we traverse the root array. At each level of traversing, we either return the object at that level acc[part] if it already exists, or we create and return a new one if it doesn't (acc[part] = {}).
After we get to the the last level leaf, we use the lastPart to set the value as null.
Notice that we pass Object.create(null) to reduce. Object.create(null) creates a prototypeless object so it will ba safer to use root[someKey] without having to check if someKey is an owned property or not.
Example:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let result = buildMenuMap(arr);
console.log(result);
I like this. thanks. can you explain why the original code doesn't work or how I can fix it?
– totalnoob
Nov 14 at 22:33
add a comment |
up vote
2
down vote
I just debugged your code to see what was wrong and I urge you to do the same. You make two (obvious) mistakes:
Firstly, In the very first iteration, here the value of map is just an empty object {}, the value of root gets initialised to "" and label is swipes.
.forEach((element) => {
let root = map[element[0]] || "";
...
root = root[label];
}
So then you get root[label] is undefined and so the new root is undefined.
Second, you are using map everywhere as it is.
const addLabelToMap = (root, label) => {
if(!map[root]) map[root] = {};
if(!map[root][label]) map[root][label] = {};
}
Instead you should be taking it as a parameter, for you to be able to do a recursion.
const addLabelToMap = (root, label) => {
if(!root[label]) root[label] = {};
}
To debug you code, create a simple HTML file with the js in the script tags and then serve it from your local machine using python -m http.server. You can then add a debug point and go through your code step by step.
add a comment |
up vote
2
down vote
Try this as a holistic solution:
const menu = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
const deepMerge = (target, source) => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (let key of Object.keys(source)) {
if (source[key] instanceof Object && key in target) Object.assign(source[key], deepMerge(target[key], source[key]))
}
// Join `target` and modified `source`
Object.assign(target || {}, source)
return target
};
const buildMenuMap = menu => {
return menu
.map(item => item.split('/').splice(1))
// The `root` value is the object that we will be merging all directories into
.reduce((root, directory) => {
// Iterates backwards through each directory array, stacking the previous accumulated object into the current one
const branch = directory.slice().reverse().reduce((acc, cur) => { const obj = {}; obj[cur] = acc; return obj;},null);
// Uses the `deepMerge()` method to stitch together the accumulated `root` object with the newly constructed `branch` object.
return deepMerge(root, branch);
}, {});
};
buildMenuMap(menu);
Note: The deep merge solution was taken from @ahtcx on GitHubGist
add a comment |
up vote
2
down vote
You can simplify your code using Array.reduce, Object.keys & String.substring
buildMenuMap
The function takes the array as input and reduce it into an object where for each entry in array, the object is updated with corresponding hierarchy using addLabelToMap function. Each entry is converted into an array of levels (c.substring(1).split("/")).
addLabelToMap
The function takes 2 inputs
obj - the current root object / node
ar - array of child hierarchy
and returns the updated object
Logic
- function pops the first value (
let key = ar.shift()) as key and add / update in the object (obj[key] = obj[key] || {};). - If there is child hierarchy of current object (
if(ar.length)), recursively call the function to update the object till the end (addLabelToMap(obj[key], ar)). - Else (no further child hierarchy), check whether the object has some hierarchy (
else if(!Object.keys(obj[key]).length)) because of other entries in array. If there is no hierarchy, i.e. it is a leaf, hence, set the value tonull(obj[key] = null). Note, if there will never be case where there is an entry in array like/social/swipes/men/youngalong with existing, theelse ifblock can be simplified to a simpleelseblock. - The object has been update, return the final updated object
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
function addLabelToMap(obj, ar) {
let key = ar.shift();
obj[key] = obj[key] || {};
if(ar.length) addLabelToMap(obj[key], ar);
else if(!Object.keys(obj[key]).length) obj[key] = null;
return obj;
}
function buildMenuMap(ar) {
return ar.reduce((a,c) => addLabelToMap(a,c.substring(1).split("/")), {});
}
console.log(buildMenuMap(arr));add a comment |
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
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)
how does let keys = d.split('/').filter(d => d) remove the empty entries?
– totalnoob
Nov 25 at 19:23
.splitwill split the string based on '/'. So string/social/swipes/womenwill become - ['', social,swipes,women] andfilterwill then removefalsyvalues and emoty string is a falsy value
– Nitish Narang
Nov 25 at 19:25
1
.filter(d => d)represents filter onlytruthyvalue
– Nitish Narang
Nov 25 at 19:26
Falsyvalues Doc - developer.mozilla.org/en-US/docs/Glossary/Falsy
– Nitish Narang
Nov 25 at 19:27
clear and simple. thanks
– totalnoob
Nov 25 at 19:27
|
show 4 more comments
up vote
5
down vote
accepted
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)
how does let keys = d.split('/').filter(d => d) remove the empty entries?
– totalnoob
Nov 25 at 19:23
.splitwill split the string based on '/'. So string/social/swipes/womenwill become - ['', social,swipes,women] andfilterwill then removefalsyvalues and emoty string is a falsy value
– Nitish Narang
Nov 25 at 19:25
1
.filter(d => d)represents filter onlytruthyvalue
– Nitish Narang
Nov 25 at 19:26
Falsyvalues Doc - developer.mozilla.org/en-US/docs/Glossary/Falsy
– Nitish Narang
Nov 25 at 19:27
clear and simple. thanks
– totalnoob
Nov 25 at 19:27
|
show 4 more comments
up vote
5
down vote
accepted
up vote
5
down vote
accepted
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)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)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)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)answered Nov 23 at 20:29
Nitish Narang
2,850812
2,850812
how does let keys = d.split('/').filter(d => d) remove the empty entries?
– totalnoob
Nov 25 at 19:23
.splitwill split the string based on '/'. So string/social/swipes/womenwill become - ['', social,swipes,women] andfilterwill then removefalsyvalues and emoty string is a falsy value
– Nitish Narang
Nov 25 at 19:25
1
.filter(d => d)represents filter onlytruthyvalue
– Nitish Narang
Nov 25 at 19:26
Falsyvalues Doc - developer.mozilla.org/en-US/docs/Glossary/Falsy
– Nitish Narang
Nov 25 at 19:27
clear and simple. thanks
– totalnoob
Nov 25 at 19:27
|
show 4 more comments
how does let keys = d.split('/').filter(d => d) remove the empty entries?
– totalnoob
Nov 25 at 19:23
.splitwill split the string based on '/'. So string/social/swipes/womenwill become - ['', social,swipes,women] andfilterwill then removefalsyvalues and emoty string is a falsy value
– Nitish Narang
Nov 25 at 19:25
1
.filter(d => d)represents filter onlytruthyvalue
– Nitish Narang
Nov 25 at 19:26
Falsyvalues Doc - developer.mozilla.org/en-US/docs/Glossary/Falsy
– Nitish Narang
Nov 25 at 19:27
clear and simple. thanks
– totalnoob
Nov 25 at 19:27
how does let keys = d.split('/').filter(d => d) remove the empty entries?
– totalnoob
Nov 25 at 19:23
how does let keys = d.split('/').filter(d => d) remove the empty entries?
– totalnoob
Nov 25 at 19:23
.split will split the string based on '/'. So string /social/swipes/women will become - ['', social,swipes,women] and filter will then remove falsy values and emoty string is a falsy value– Nitish Narang
Nov 25 at 19:25
.split will split the string based on '/'. So string /social/swipes/women will become - ['', social,swipes,women] and filter will then remove falsy values and emoty string is a falsy value– Nitish Narang
Nov 25 at 19:25
1
1
.filter(d => d) represents filter only truthy value– Nitish Narang
Nov 25 at 19:26
.filter(d => d) represents filter only truthy value– Nitish Narang
Nov 25 at 19:26
Falsy values Doc - developer.mozilla.org/en-US/docs/Glossary/Falsy– Nitish Narang
Nov 25 at 19:27
Falsy values Doc - developer.mozilla.org/en-US/docs/Glossary/Falsy– Nitish Narang
Nov 25 at 19:27
clear and simple. thanks
– totalnoob
Nov 25 at 19:27
clear and simple. thanks
– totalnoob
Nov 25 at 19:27
|
show 4 more comments
up vote
3
down vote
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;
}
it didn't work when I tried it
– totalnoob
Nov 14 at 21:26
that's awesome. can you tell me why the current code doesn't work even setting root properly?
– totalnoob
Nov 14 at 21:31
@totalnoob becauseaddLabelToMapdoes not go deeper into the map
– Jonas Wilms
Nov 14 at 21:32
when I use root = root[label], on the next loop root is undefined if I print it out
– totalnoob
Nov 14 at 21:38
add a comment |
up vote
3
down vote
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;
}
it didn't work when I tried it
– totalnoob
Nov 14 at 21:26
that's awesome. can you tell me why the current code doesn't work even setting root properly?
– totalnoob
Nov 14 at 21:31
@totalnoob becauseaddLabelToMapdoes not go deeper into the map
– Jonas Wilms
Nov 14 at 21:32
when I use root = root[label], on the next loop root is undefined if I print it out
– totalnoob
Nov 14 at 21:38
add a comment |
up vote
3
down vote
up vote
3
down vote
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;
}
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;
}
edited Nov 14 at 21:31
answered Nov 14 at 21:25
Jonas Wilms
53.1k42447
53.1k42447
it didn't work when I tried it
– totalnoob
Nov 14 at 21:26
that's awesome. can you tell me why the current code doesn't work even setting root properly?
– totalnoob
Nov 14 at 21:31
@totalnoob becauseaddLabelToMapdoes not go deeper into the map
– Jonas Wilms
Nov 14 at 21:32
when I use root = root[label], on the next loop root is undefined if I print it out
– totalnoob
Nov 14 at 21:38
add a comment |
it didn't work when I tried it
– totalnoob
Nov 14 at 21:26
that's awesome. can you tell me why the current code doesn't work even setting root properly?
– totalnoob
Nov 14 at 21:31
@totalnoob becauseaddLabelToMapdoes not go deeper into the map
– Jonas Wilms
Nov 14 at 21:32
when I use root = root[label], on the next loop root is undefined if I print it out
– totalnoob
Nov 14 at 21:38
it didn't work when I tried it
– totalnoob
Nov 14 at 21:26
it didn't work when I tried it
– totalnoob
Nov 14 at 21:26
that's awesome. can you tell me why the current code doesn't work even setting root properly?
– totalnoob
Nov 14 at 21:31
that's awesome. can you tell me why the current code doesn't work even setting root properly?
– totalnoob
Nov 14 at 21:31
@totalnoob because
addLabelToMap does not go deeper into the map– Jonas Wilms
Nov 14 at 21:32
@totalnoob because
addLabelToMap does not go deeper into the map– Jonas Wilms
Nov 14 at 21:32
when I use root = root[label], on the next loop root is undefined if I print it out
– totalnoob
Nov 14 at 21:38
when I use root = root[label], on the next loop root is undefined if I print it out
– totalnoob
Nov 14 at 21:38
add a comment |
up vote
2
down vote
Use reduce instead of map. The root will be the accumulator in this case:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
Explanation:
For each item in the menu array, we extract the parts by first getting rid of the leading '/' (using slice(1)) and then splitting by '/'.
We then remove the lastPart from this resulting array (the last part is handled separetely from the rest).
For each remaining part in the parts array, we traverse the root array. At each level of traversing, we either return the object at that level acc[part] if it already exists, or we create and return a new one if it doesn't (acc[part] = {}).
After we get to the the last level leaf, we use the lastPart to set the value as null.
Notice that we pass Object.create(null) to reduce. Object.create(null) creates a prototypeless object so it will ba safer to use root[someKey] without having to check if someKey is an owned property or not.
Example:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let result = buildMenuMap(arr);
console.log(result);
I like this. thanks. can you explain why the original code doesn't work or how I can fix it?
– totalnoob
Nov 14 at 22:33
add a comment |
up vote
2
down vote
Use reduce instead of map. The root will be the accumulator in this case:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
Explanation:
For each item in the menu array, we extract the parts by first getting rid of the leading '/' (using slice(1)) and then splitting by '/'.
We then remove the lastPart from this resulting array (the last part is handled separetely from the rest).
For each remaining part in the parts array, we traverse the root array. At each level of traversing, we either return the object at that level acc[part] if it already exists, or we create and return a new one if it doesn't (acc[part] = {}).
After we get to the the last level leaf, we use the lastPart to set the value as null.
Notice that we pass Object.create(null) to reduce. Object.create(null) creates a prototypeless object so it will ba safer to use root[someKey] without having to check if someKey is an owned property or not.
Example:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let result = buildMenuMap(arr);
console.log(result);
I like this. thanks. can you explain why the original code doesn't work or how I can fix it?
– totalnoob
Nov 14 at 22:33
add a comment |
up vote
2
down vote
up vote
2
down vote
Use reduce instead of map. The root will be the accumulator in this case:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
Explanation:
For each item in the menu array, we extract the parts by first getting rid of the leading '/' (using slice(1)) and then splitting by '/'.
We then remove the lastPart from this resulting array (the last part is handled separetely from the rest).
For each remaining part in the parts array, we traverse the root array. At each level of traversing, we either return the object at that level acc[part] if it already exists, or we create and return a new one if it doesn't (acc[part] = {}).
After we get to the the last level leaf, we use the lastPart to set the value as null.
Notice that we pass Object.create(null) to reduce. Object.create(null) creates a prototypeless object so it will ba safer to use root[someKey] without having to check if someKey is an owned property or not.
Example:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let result = buildMenuMap(arr);
console.log(result);Use reduce instead of map. The root will be the accumulator in this case:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
Explanation:
For each item in the menu array, we extract the parts by first getting rid of the leading '/' (using slice(1)) and then splitting by '/'.
We then remove the lastPart from this resulting array (the last part is handled separetely from the rest).
For each remaining part in the parts array, we traverse the root array. At each level of traversing, we either return the object at that level acc[part] if it already exists, or we create and return a new one if it doesn't (acc[part] = {}).
After we get to the the last level leaf, we use the lastPart to set the value as null.
Notice that we pass Object.create(null) to reduce. Object.create(null) creates a prototypeless object so it will ba safer to use root[someKey] without having to check if someKey is an owned property or not.
Example:
const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let result = buildMenuMap(arr);
console.log(result);const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let result = buildMenuMap(arr);
console.log(result);const buildMenuMap = menu =>
menu.reduce((root, item) => {
let parts = item.slice(1).split("/");
let lastPart = parts.pop();
let leaf = parts.reduce((acc, part) => acc[part] || (acc[part] = {}), root);
leaf[lastPart] = null;
return root;
}, Object.create(null));
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
let result = buildMenuMap(arr);
console.log(result);edited Nov 14 at 21:36
answered Nov 14 at 21:30
ibrahim mahrir
21.1k41746
21.1k41746
I like this. thanks. can you explain why the original code doesn't work or how I can fix it?
– totalnoob
Nov 14 at 22:33
add a comment |
I like this. thanks. can you explain why the original code doesn't work or how I can fix it?
– totalnoob
Nov 14 at 22:33
I like this. thanks. can you explain why the original code doesn't work or how I can fix it?
– totalnoob
Nov 14 at 22:33
I like this. thanks. can you explain why the original code doesn't work or how I can fix it?
– totalnoob
Nov 14 at 22:33
add a comment |
up vote
2
down vote
I just debugged your code to see what was wrong and I urge you to do the same. You make two (obvious) mistakes:
Firstly, In the very first iteration, here the value of map is just an empty object {}, the value of root gets initialised to "" and label is swipes.
.forEach((element) => {
let root = map[element[0]] || "";
...
root = root[label];
}
So then you get root[label] is undefined and so the new root is undefined.
Second, you are using map everywhere as it is.
const addLabelToMap = (root, label) => {
if(!map[root]) map[root] = {};
if(!map[root][label]) map[root][label] = {};
}
Instead you should be taking it as a parameter, for you to be able to do a recursion.
const addLabelToMap = (root, label) => {
if(!root[label]) root[label] = {};
}
To debug you code, create a simple HTML file with the js in the script tags and then serve it from your local machine using python -m http.server. You can then add a debug point and go through your code step by step.
add a comment |
up vote
2
down vote
I just debugged your code to see what was wrong and I urge you to do the same. You make two (obvious) mistakes:
Firstly, In the very first iteration, here the value of map is just an empty object {}, the value of root gets initialised to "" and label is swipes.
.forEach((element) => {
let root = map[element[0]] || "";
...
root = root[label];
}
So then you get root[label] is undefined and so the new root is undefined.
Second, you are using map everywhere as it is.
const addLabelToMap = (root, label) => {
if(!map[root]) map[root] = {};
if(!map[root][label]) map[root][label] = {};
}
Instead you should be taking it as a parameter, for you to be able to do a recursion.
const addLabelToMap = (root, label) => {
if(!root[label]) root[label] = {};
}
To debug you code, create a simple HTML file with the js in the script tags and then serve it from your local machine using python -m http.server. You can then add a debug point and go through your code step by step.
add a comment |
up vote
2
down vote
up vote
2
down vote
I just debugged your code to see what was wrong and I urge you to do the same. You make two (obvious) mistakes:
Firstly, In the very first iteration, here the value of map is just an empty object {}, the value of root gets initialised to "" and label is swipes.
.forEach((element) => {
let root = map[element[0]] || "";
...
root = root[label];
}
So then you get root[label] is undefined and so the new root is undefined.
Second, you are using map everywhere as it is.
const addLabelToMap = (root, label) => {
if(!map[root]) map[root] = {};
if(!map[root][label]) map[root][label] = {};
}
Instead you should be taking it as a parameter, for you to be able to do a recursion.
const addLabelToMap = (root, label) => {
if(!root[label]) root[label] = {};
}
To debug you code, create a simple HTML file with the js in the script tags and then serve it from your local machine using python -m http.server. You can then add a debug point and go through your code step by step.
I just debugged your code to see what was wrong and I urge you to do the same. You make two (obvious) mistakes:
Firstly, In the very first iteration, here the value of map is just an empty object {}, the value of root gets initialised to "" and label is swipes.
.forEach((element) => {
let root = map[element[0]] || "";
...
root = root[label];
}
So then you get root[label] is undefined and so the new root is undefined.
Second, you are using map everywhere as it is.
const addLabelToMap = (root, label) => {
if(!map[root]) map[root] = {};
if(!map[root][label]) map[root][label] = {};
}
Instead you should be taking it as a parameter, for you to be able to do a recursion.
const addLabelToMap = (root, label) => {
if(!root[label]) root[label] = {};
}
To debug you code, create a simple HTML file with the js in the script tags and then serve it from your local machine using python -m http.server. You can then add a debug point and go through your code step by step.
answered Nov 18 at 15:48
TheChetan
2,23711530
2,23711530
add a comment |
add a comment |
up vote
2
down vote
Try this as a holistic solution:
const menu = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
const deepMerge = (target, source) => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (let key of Object.keys(source)) {
if (source[key] instanceof Object && key in target) Object.assign(source[key], deepMerge(target[key], source[key]))
}
// Join `target` and modified `source`
Object.assign(target || {}, source)
return target
};
const buildMenuMap = menu => {
return menu
.map(item => item.split('/').splice(1))
// The `root` value is the object that we will be merging all directories into
.reduce((root, directory) => {
// Iterates backwards through each directory array, stacking the previous accumulated object into the current one
const branch = directory.slice().reverse().reduce((acc, cur) => { const obj = {}; obj[cur] = acc; return obj;},null);
// Uses the `deepMerge()` method to stitch together the accumulated `root` object with the newly constructed `branch` object.
return deepMerge(root, branch);
}, {});
};
buildMenuMap(menu);
Note: The deep merge solution was taken from @ahtcx on GitHubGist
add a comment |
up vote
2
down vote
Try this as a holistic solution:
const menu = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
const deepMerge = (target, source) => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (let key of Object.keys(source)) {
if (source[key] instanceof Object && key in target) Object.assign(source[key], deepMerge(target[key], source[key]))
}
// Join `target` and modified `source`
Object.assign(target || {}, source)
return target
};
const buildMenuMap = menu => {
return menu
.map(item => item.split('/').splice(1))
// The `root` value is the object that we will be merging all directories into
.reduce((root, directory) => {
// Iterates backwards through each directory array, stacking the previous accumulated object into the current one
const branch = directory.slice().reverse().reduce((acc, cur) => { const obj = {}; obj[cur] = acc; return obj;},null);
// Uses the `deepMerge()` method to stitch together the accumulated `root` object with the newly constructed `branch` object.
return deepMerge(root, branch);
}, {});
};
buildMenuMap(menu);
Note: The deep merge solution was taken from @ahtcx on GitHubGist
add a comment |
up vote
2
down vote
up vote
2
down vote
Try this as a holistic solution:
const menu = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
const deepMerge = (target, source) => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (let key of Object.keys(source)) {
if (source[key] instanceof Object && key in target) Object.assign(source[key], deepMerge(target[key], source[key]))
}
// Join `target` and modified `source`
Object.assign(target || {}, source)
return target
};
const buildMenuMap = menu => {
return menu
.map(item => item.split('/').splice(1))
// The `root` value is the object that we will be merging all directories into
.reduce((root, directory) => {
// Iterates backwards through each directory array, stacking the previous accumulated object into the current one
const branch = directory.slice().reverse().reduce((acc, cur) => { const obj = {}; obj[cur] = acc; return obj;},null);
// Uses the `deepMerge()` method to stitch together the accumulated `root` object with the newly constructed `branch` object.
return deepMerge(root, branch);
}, {});
};
buildMenuMap(menu);
Note: The deep merge solution was taken from @ahtcx on GitHubGist
Try this as a holistic solution:
const menu = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
const deepMerge = (target, source) => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (let key of Object.keys(source)) {
if (source[key] instanceof Object && key in target) Object.assign(source[key], deepMerge(target[key], source[key]))
}
// Join `target` and modified `source`
Object.assign(target || {}, source)
return target
};
const buildMenuMap = menu => {
return menu
.map(item => item.split('/').splice(1))
// The `root` value is the object that we will be merging all directories into
.reduce((root, directory) => {
// Iterates backwards through each directory array, stacking the previous accumulated object into the current one
const branch = directory.slice().reverse().reduce((acc, cur) => { const obj = {}; obj[cur] = acc; return obj;},null);
// Uses the `deepMerge()` method to stitch together the accumulated `root` object with the newly constructed `branch` object.
return deepMerge(root, branch);
}, {});
};
buildMenuMap(menu);
Note: The deep merge solution was taken from @ahtcx on GitHubGist
edited Nov 19 at 21:02
answered Nov 19 at 20:54
astangelo
458
458
add a comment |
add a comment |
up vote
2
down vote
You can simplify your code using Array.reduce, Object.keys & String.substring
buildMenuMap
The function takes the array as input and reduce it into an object where for each entry in array, the object is updated with corresponding hierarchy using addLabelToMap function. Each entry is converted into an array of levels (c.substring(1).split("/")).
addLabelToMap
The function takes 2 inputs
obj - the current root object / node
ar - array of child hierarchy
and returns the updated object
Logic
- function pops the first value (
let key = ar.shift()) as key and add / update in the object (obj[key] = obj[key] || {};). - If there is child hierarchy of current object (
if(ar.length)), recursively call the function to update the object till the end (addLabelToMap(obj[key], ar)). - Else (no further child hierarchy), check whether the object has some hierarchy (
else if(!Object.keys(obj[key]).length)) because of other entries in array. If there is no hierarchy, i.e. it is a leaf, hence, set the value tonull(obj[key] = null). Note, if there will never be case where there is an entry in array like/social/swipes/men/youngalong with existing, theelse ifblock can be simplified to a simpleelseblock. - The object has been update, return the final updated object
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
function addLabelToMap(obj, ar) {
let key = ar.shift();
obj[key] = obj[key] || {};
if(ar.length) addLabelToMap(obj[key], ar);
else if(!Object.keys(obj[key]).length) obj[key] = null;
return obj;
}
function buildMenuMap(ar) {
return ar.reduce((a,c) => addLabelToMap(a,c.substring(1).split("/")), {});
}
console.log(buildMenuMap(arr));add a comment |
up vote
2
down vote
You can simplify your code using Array.reduce, Object.keys & String.substring
buildMenuMap
The function takes the array as input and reduce it into an object where for each entry in array, the object is updated with corresponding hierarchy using addLabelToMap function. Each entry is converted into an array of levels (c.substring(1).split("/")).
addLabelToMap
The function takes 2 inputs
obj - the current root object / node
ar - array of child hierarchy
and returns the updated object
Logic
- function pops the first value (
let key = ar.shift()) as key and add / update in the object (obj[key] = obj[key] || {};). - If there is child hierarchy of current object (
if(ar.length)), recursively call the function to update the object till the end (addLabelToMap(obj[key], ar)). - Else (no further child hierarchy), check whether the object has some hierarchy (
else if(!Object.keys(obj[key]).length)) because of other entries in array. If there is no hierarchy, i.e. it is a leaf, hence, set the value tonull(obj[key] = null). Note, if there will never be case where there is an entry in array like/social/swipes/men/youngalong with existing, theelse ifblock can be simplified to a simpleelseblock. - The object has been update, return the final updated object
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
function addLabelToMap(obj, ar) {
let key = ar.shift();
obj[key] = obj[key] || {};
if(ar.length) addLabelToMap(obj[key], ar);
else if(!Object.keys(obj[key]).length) obj[key] = null;
return obj;
}
function buildMenuMap(ar) {
return ar.reduce((a,c) => addLabelToMap(a,c.substring(1).split("/")), {});
}
console.log(buildMenuMap(arr));add a comment |
up vote
2
down vote
up vote
2
down vote
You can simplify your code using Array.reduce, Object.keys & String.substring
buildMenuMap
The function takes the array as input and reduce it into an object where for each entry in array, the object is updated with corresponding hierarchy using addLabelToMap function. Each entry is converted into an array of levels (c.substring(1).split("/")).
addLabelToMap
The function takes 2 inputs
obj - the current root object / node
ar - array of child hierarchy
and returns the updated object
Logic
- function pops the first value (
let key = ar.shift()) as key and add / update in the object (obj[key] = obj[key] || {};). - If there is child hierarchy of current object (
if(ar.length)), recursively call the function to update the object till the end (addLabelToMap(obj[key], ar)). - Else (no further child hierarchy), check whether the object has some hierarchy (
else if(!Object.keys(obj[key]).length)) because of other entries in array. If there is no hierarchy, i.e. it is a leaf, hence, set the value tonull(obj[key] = null). Note, if there will never be case where there is an entry in array like/social/swipes/men/youngalong with existing, theelse ifblock can be simplified to a simpleelseblock. - The object has been update, return the final updated object
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
function addLabelToMap(obj, ar) {
let key = ar.shift();
obj[key] = obj[key] || {};
if(ar.length) addLabelToMap(obj[key], ar);
else if(!Object.keys(obj[key]).length) obj[key] = null;
return obj;
}
function buildMenuMap(ar) {
return ar.reduce((a,c) => addLabelToMap(a,c.substring(1).split("/")), {});
}
console.log(buildMenuMap(arr));You can simplify your code using Array.reduce, Object.keys & String.substring
buildMenuMap
The function takes the array as input and reduce it into an object where for each entry in array, the object is updated with corresponding hierarchy using addLabelToMap function. Each entry is converted into an array of levels (c.substring(1).split("/")).
addLabelToMap
The function takes 2 inputs
obj - the current root object / node
ar - array of child hierarchy
and returns the updated object
Logic
- function pops the first value (
let key = ar.shift()) as key and add / update in the object (obj[key] = obj[key] || {};). - If there is child hierarchy of current object (
if(ar.length)), recursively call the function to update the object till the end (addLabelToMap(obj[key], ar)). - Else (no further child hierarchy), check whether the object has some hierarchy (
else if(!Object.keys(obj[key]).length)) because of other entries in array. If there is no hierarchy, i.e. it is a leaf, hence, set the value tonull(obj[key] = null). Note, if there will never be case where there is an entry in array like/social/swipes/men/youngalong with existing, theelse ifblock can be simplified to a simpleelseblock. - The object has been update, return the final updated object
let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
function addLabelToMap(obj, ar) {
let key = ar.shift();
obj[key] = obj[key] || {};
if(ar.length) addLabelToMap(obj[key], ar);
else if(!Object.keys(obj[key]).length) obj[key] = null;
return obj;
}
function buildMenuMap(ar) {
return ar.reduce((a,c) => addLabelToMap(a,c.substring(1).split("/")), {});
}
console.log(buildMenuMap(arr));let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
function addLabelToMap(obj, ar) {
let key = ar.shift();
obj[key] = obj[key] || {};
if(ar.length) addLabelToMap(obj[key], ar);
else if(!Object.keys(obj[key]).length) obj[key] = null;
return obj;
}
function buildMenuMap(ar) {
return ar.reduce((a,c) => addLabelToMap(a,c.substring(1).split("/")), {});
}
console.log(buildMenuMap(arr));let arr = ['/social/swipes/women', '/social/swipes/men', '/upgrade/premium'];
function addLabelToMap(obj, ar) {
let key = ar.shift();
obj[key] = obj[key] || {};
if(ar.length) addLabelToMap(obj[key], ar);
else if(!Object.keys(obj[key]).length) obj[key] = null;
return obj;
}
function buildMenuMap(ar) {
return ar.reduce((a,c) => addLabelToMap(a,c.substring(1).split("/")), {});
}
console.log(buildMenuMap(arr));answered Nov 22 at 15:25
Nikhil Aggarwal
23.5k32647
23.5k32647
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53308903%2fbuilding-a-menu-list-object-recursively-in-javascript%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Shouldn't
menbe in thelikesobject not theswipesobject?– ibrahim mahrir
Nov 14 at 21:22
I've just edited it
– totalnoob
Nov 14 at 21:23