Create nested array data from an array of objects
I have an array of objects that has information of nested data, and I want to convert the data to actual nested array data.
How can I convert this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
to this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{
id: 2,
parent_id: null,
name: 'test2',
children: [
{id: 3, parent_id: 2, name: 'test3'},
{
id: 4,
parent_id: 2,
name: 'test4',
children: [
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'}
]
},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
]
},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
What is the best way to do this?
javascript arrays json
add a comment |
I have an array of objects that has information of nested data, and I want to convert the data to actual nested array data.
How can I convert this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
to this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{
id: 2,
parent_id: null,
name: 'test2',
children: [
{id: 3, parent_id: 2, name: 'test3'},
{
id: 4,
parent_id: 2,
name: 'test4',
children: [
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'}
]
},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
]
},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
What is the best way to do this?
javascript arrays json
add a comment |
I have an array of objects that has information of nested data, and I want to convert the data to actual nested array data.
How can I convert this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
to this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{
id: 2,
parent_id: null,
name: 'test2',
children: [
{id: 3, parent_id: 2, name: 'test3'},
{
id: 4,
parent_id: 2,
name: 'test4',
children: [
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'}
]
},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
]
},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
What is the best way to do this?
javascript arrays json
I have an array of objects that has information of nested data, and I want to convert the data to actual nested array data.
How can I convert this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
to this:
const data = [
{id: 1, parent_id: null, name: 'test1'},
{
id: 2,
parent_id: null,
name: 'test2',
children: [
{id: 3, parent_id: 2, name: 'test3'},
{
id: 4,
parent_id: 2,
name: 'test4',
children: [
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'}
]
},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
]
},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
What is the best way to do this?
javascript arrays json
javascript arrays json
edited Nov 20 '18 at 22:19
Dan
asked Nov 20 '18 at 15:21
DanDan
5741514
5741514
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
You could create recursive function with reduce
method for this.
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
function nest(data, parentId = null) {
return data.reduce((r, e) => {
let obj = Object.assign({}, e)
if (parentId == e.parent_id) {
let children = nest(data, e.id)
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, )
}
console.log(nest(data))
add a comment |
You could take a single loop approach by using an object and the id
and parent_id
as key and collect the items/children to it.
The order is only important for the order in the children array.
const
data = [{ id: 1, parent_id: null, name: 'test1' }, { id: 2, parent_id: null, name: 'test2' }, { id: 3, parent_id: 2, name: 'test3' }, { id: 4, parent_id: 2, name: 'test4' }, { id: 5, parent_id: 4, name: 'test5' }, { id: 6, parent_id: 4, name: 'test5' }, { id: 7, parent_id: 2, name: 'test5' }, { id: 8, parent_id: 2, name: 'test5' }, { id: 9, parent_id: null, name: 'test5' }, { id: 10, parent_id: null, name: 'test5' }],
tree = function (data, root) {
var o = {};
data.forEach(function (a) {
Object.assign(o[a.id] = o[a.id] || {}, a, o[a.id] && o[a.id].children && { children: o[a.id].children });
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || ;
o[a.parent_id].children.push(o[a.id]);
});
return o[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Does this depend on the order? For example ifid:1
has a parent of4
, it seems like it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 15:48
@MarkMeyer, the order does not matter for parent children relations.
– Nina Scholz
Nov 20 '18 at 15:52
Hmm, not sure what it is. If I change the parent of itemid:1
fromnull
to4
it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 16:01
please look below, children array comes first, but the item is in the right place.
– Nina Scholz
Nov 20 '18 at 16:04
I apologize — you are right! Just couldn't read my own output :(.
– Mark Meyer
Nov 20 '18 at 16:06
add a comment |
This is an interesting problem. One option if you want to keep linear time at the expense of some space it to make a lookup object based on id
. Then you can loop through those values and push into either a parent object or the array:
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
let lookup = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
let arr = Object.values(lookup).reduce((arr, val) =>{
if (val.parent_id == null) arr.push(val)
else (lookup[val.parent_id].children || ( lookup[val.parent_id].children = )).push(val)
return arr
}, )
console.log(JSON.stringify(arr, null, 2))
add a comment |
you could try this recursive approach
const data = [{id: 1, parent_id: null, name: 'test1'}, {id: 2, parent_id: null, name: 'test2'}, {id: 3, parent_id: 2, name: 'test3'}, {id: 4, parent_id: 2, name: 'test4'}, {id: 5, parent_id: 4, name: 'test5'}, {id: 6, parent_id: 4, name: 'test5'}, {id: 7, parent_id: 2, name: 'test5'}, {id: 8, parent_id: 2, name: 'test5'}, {id: 9, parent_id: null, name: 'test5'}, {id: 10, parent_id: null, name: 'test5'}];
const transform = arr => {
return arr.reduce((acc, elem) => {
const children = data.filter(el => el.parent_id === elem.id),
isPresent = findDeep(acc, elem);
if(!isPresent && children.length)
acc.push({...elem, children: transform(children)});
else if(!isPresent)
acc.push(elem);
return acc;
}, );
}
const findDeep =(arr = , elem) => (
arr.some(el => (el.id === elem.id) || findDeep(el.children, elem))
);
console.log(transform(data));
add a comment |
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
const output = data.filter(
item => !item.parent_id
).map(
rootItem => ({
...rootItem,
children: data.filter(item => item.parent_id === rootItem.id),
})
)
console.log(output)
1
What happened it id: 5?
– Mark Meyer
Nov 20 '18 at 15:37
Ah you're right there is more than one level of nesting, the best answer is probably the one using reduce.
– alexjackson
Nov 20 '18 at 15:39
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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%2f53396194%2fcreate-nested-array-data-from-an-array-of-objects%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could create recursive function with reduce
method for this.
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
function nest(data, parentId = null) {
return data.reduce((r, e) => {
let obj = Object.assign({}, e)
if (parentId == e.parent_id) {
let children = nest(data, e.id)
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, )
}
console.log(nest(data))
add a comment |
You could create recursive function with reduce
method for this.
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
function nest(data, parentId = null) {
return data.reduce((r, e) => {
let obj = Object.assign({}, e)
if (parentId == e.parent_id) {
let children = nest(data, e.id)
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, )
}
console.log(nest(data))
add a comment |
You could create recursive function with reduce
method for this.
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
function nest(data, parentId = null) {
return data.reduce((r, e) => {
let obj = Object.assign({}, e)
if (parentId == e.parent_id) {
let children = nest(data, e.id)
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, )
}
console.log(nest(data))
You could create recursive function with reduce
method for this.
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
function nest(data, parentId = null) {
return data.reduce((r, e) => {
let obj = Object.assign({}, e)
if (parentId == e.parent_id) {
let children = nest(data, e.id)
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, )
}
console.log(nest(data))
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
function nest(data, parentId = null) {
return data.reduce((r, e) => {
let obj = Object.assign({}, e)
if (parentId == e.parent_id) {
let children = nest(data, e.id)
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, )
}
console.log(nest(data))
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
function nest(data, parentId = null) {
return data.reduce((r, e) => {
let obj = Object.assign({}, e)
if (parentId == e.parent_id) {
let children = nest(data, e.id)
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, )
}
console.log(nest(data))
answered Nov 20 '18 at 15:34


Nenad VracarNenad Vracar
71k115679
71k115679
add a comment |
add a comment |
You could take a single loop approach by using an object and the id
and parent_id
as key and collect the items/children to it.
The order is only important for the order in the children array.
const
data = [{ id: 1, parent_id: null, name: 'test1' }, { id: 2, parent_id: null, name: 'test2' }, { id: 3, parent_id: 2, name: 'test3' }, { id: 4, parent_id: 2, name: 'test4' }, { id: 5, parent_id: 4, name: 'test5' }, { id: 6, parent_id: 4, name: 'test5' }, { id: 7, parent_id: 2, name: 'test5' }, { id: 8, parent_id: 2, name: 'test5' }, { id: 9, parent_id: null, name: 'test5' }, { id: 10, parent_id: null, name: 'test5' }],
tree = function (data, root) {
var o = {};
data.forEach(function (a) {
Object.assign(o[a.id] = o[a.id] || {}, a, o[a.id] && o[a.id].children && { children: o[a.id].children });
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || ;
o[a.parent_id].children.push(o[a.id]);
});
return o[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Does this depend on the order? For example ifid:1
has a parent of4
, it seems like it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 15:48
@MarkMeyer, the order does not matter for parent children relations.
– Nina Scholz
Nov 20 '18 at 15:52
Hmm, not sure what it is. If I change the parent of itemid:1
fromnull
to4
it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 16:01
please look below, children array comes first, but the item is in the right place.
– Nina Scholz
Nov 20 '18 at 16:04
I apologize — you are right! Just couldn't read my own output :(.
– Mark Meyer
Nov 20 '18 at 16:06
add a comment |
You could take a single loop approach by using an object and the id
and parent_id
as key and collect the items/children to it.
The order is only important for the order in the children array.
const
data = [{ id: 1, parent_id: null, name: 'test1' }, { id: 2, parent_id: null, name: 'test2' }, { id: 3, parent_id: 2, name: 'test3' }, { id: 4, parent_id: 2, name: 'test4' }, { id: 5, parent_id: 4, name: 'test5' }, { id: 6, parent_id: 4, name: 'test5' }, { id: 7, parent_id: 2, name: 'test5' }, { id: 8, parent_id: 2, name: 'test5' }, { id: 9, parent_id: null, name: 'test5' }, { id: 10, parent_id: null, name: 'test5' }],
tree = function (data, root) {
var o = {};
data.forEach(function (a) {
Object.assign(o[a.id] = o[a.id] || {}, a, o[a.id] && o[a.id].children && { children: o[a.id].children });
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || ;
o[a.parent_id].children.push(o[a.id]);
});
return o[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Does this depend on the order? For example ifid:1
has a parent of4
, it seems like it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 15:48
@MarkMeyer, the order does not matter for parent children relations.
– Nina Scholz
Nov 20 '18 at 15:52
Hmm, not sure what it is. If I change the parent of itemid:1
fromnull
to4
it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 16:01
please look below, children array comes first, but the item is in the right place.
– Nina Scholz
Nov 20 '18 at 16:04
I apologize — you are right! Just couldn't read my own output :(.
– Mark Meyer
Nov 20 '18 at 16:06
add a comment |
You could take a single loop approach by using an object and the id
and parent_id
as key and collect the items/children to it.
The order is only important for the order in the children array.
const
data = [{ id: 1, parent_id: null, name: 'test1' }, { id: 2, parent_id: null, name: 'test2' }, { id: 3, parent_id: 2, name: 'test3' }, { id: 4, parent_id: 2, name: 'test4' }, { id: 5, parent_id: 4, name: 'test5' }, { id: 6, parent_id: 4, name: 'test5' }, { id: 7, parent_id: 2, name: 'test5' }, { id: 8, parent_id: 2, name: 'test5' }, { id: 9, parent_id: null, name: 'test5' }, { id: 10, parent_id: null, name: 'test5' }],
tree = function (data, root) {
var o = {};
data.forEach(function (a) {
Object.assign(o[a.id] = o[a.id] || {}, a, o[a.id] && o[a.id].children && { children: o[a.id].children });
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || ;
o[a.parent_id].children.push(o[a.id]);
});
return o[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could take a single loop approach by using an object and the id
and parent_id
as key and collect the items/children to it.
The order is only important for the order in the children array.
const
data = [{ id: 1, parent_id: null, name: 'test1' }, { id: 2, parent_id: null, name: 'test2' }, { id: 3, parent_id: 2, name: 'test3' }, { id: 4, parent_id: 2, name: 'test4' }, { id: 5, parent_id: 4, name: 'test5' }, { id: 6, parent_id: 4, name: 'test5' }, { id: 7, parent_id: 2, name: 'test5' }, { id: 8, parent_id: 2, name: 'test5' }, { id: 9, parent_id: null, name: 'test5' }, { id: 10, parent_id: null, name: 'test5' }],
tree = function (data, root) {
var o = {};
data.forEach(function (a) {
Object.assign(o[a.id] = o[a.id] || {}, a, o[a.id] && o[a.id].children && { children: o[a.id].children });
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || ;
o[a.parent_id].children.push(o[a.id]);
});
return o[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const
data = [{ id: 1, parent_id: null, name: 'test1' }, { id: 2, parent_id: null, name: 'test2' }, { id: 3, parent_id: 2, name: 'test3' }, { id: 4, parent_id: 2, name: 'test4' }, { id: 5, parent_id: 4, name: 'test5' }, { id: 6, parent_id: 4, name: 'test5' }, { id: 7, parent_id: 2, name: 'test5' }, { id: 8, parent_id: 2, name: 'test5' }, { id: 9, parent_id: null, name: 'test5' }, { id: 10, parent_id: null, name: 'test5' }],
tree = function (data, root) {
var o = {};
data.forEach(function (a) {
Object.assign(o[a.id] = o[a.id] || {}, a, o[a.id] && o[a.id].children && { children: o[a.id].children });
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || ;
o[a.parent_id].children.push(o[a.id]);
});
return o[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const
data = [{ id: 1, parent_id: null, name: 'test1' }, { id: 2, parent_id: null, name: 'test2' }, { id: 3, parent_id: 2, name: 'test3' }, { id: 4, parent_id: 2, name: 'test4' }, { id: 5, parent_id: 4, name: 'test5' }, { id: 6, parent_id: 4, name: 'test5' }, { id: 7, parent_id: 2, name: 'test5' }, { id: 8, parent_id: 2, name: 'test5' }, { id: 9, parent_id: null, name: 'test5' }, { id: 10, parent_id: null, name: 'test5' }],
tree = function (data, root) {
var o = {};
data.forEach(function (a) {
Object.assign(o[a.id] = o[a.id] || {}, a, o[a.id] && o[a.id].children && { children: o[a.id].children });
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || ;
o[a.parent_id].children.push(o[a.id]);
});
return o[root].children;
}(data, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
edited Nov 20 '18 at 15:51
answered Nov 20 '18 at 15:39


Nina ScholzNina Scholz
181k1494163
181k1494163
Does this depend on the order? For example ifid:1
has a parent of4
, it seems like it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 15:48
@MarkMeyer, the order does not matter for parent children relations.
– Nina Scholz
Nov 20 '18 at 15:52
Hmm, not sure what it is. If I change the parent of itemid:1
fromnull
to4
it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 16:01
please look below, children array comes first, but the item is in the right place.
– Nina Scholz
Nov 20 '18 at 16:04
I apologize — you are right! Just couldn't read my own output :(.
– Mark Meyer
Nov 20 '18 at 16:06
add a comment |
Does this depend on the order? For example ifid:1
has a parent of4
, it seems like it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 15:48
@MarkMeyer, the order does not matter for parent children relations.
– Nina Scholz
Nov 20 '18 at 15:52
Hmm, not sure what it is. If I change the parent of itemid:1
fromnull
to4
it ends up in the wrong place.
– Mark Meyer
Nov 20 '18 at 16:01
please look below, children array comes first, but the item is in the right place.
– Nina Scholz
Nov 20 '18 at 16:04
I apologize — you are right! Just couldn't read my own output :(.
– Mark Meyer
Nov 20 '18 at 16:06
Does this depend on the order? For example if
id:1
has a parent of 4
, it seems like it ends up in the wrong place.– Mark Meyer
Nov 20 '18 at 15:48
Does this depend on the order? For example if
id:1
has a parent of 4
, it seems like it ends up in the wrong place.– Mark Meyer
Nov 20 '18 at 15:48
@MarkMeyer, the order does not matter for parent children relations.
– Nina Scholz
Nov 20 '18 at 15:52
@MarkMeyer, the order does not matter for parent children relations.
– Nina Scholz
Nov 20 '18 at 15:52
Hmm, not sure what it is. If I change the parent of item
id:1
from null
to 4
it ends up in the wrong place.– Mark Meyer
Nov 20 '18 at 16:01
Hmm, not sure what it is. If I change the parent of item
id:1
from null
to 4
it ends up in the wrong place.– Mark Meyer
Nov 20 '18 at 16:01
please look below, children array comes first, but the item is in the right place.
– Nina Scholz
Nov 20 '18 at 16:04
please look below, children array comes first, but the item is in the right place.
– Nina Scholz
Nov 20 '18 at 16:04
I apologize — you are right! Just couldn't read my own output :(.
– Mark Meyer
Nov 20 '18 at 16:06
I apologize — you are right! Just couldn't read my own output :(.
– Mark Meyer
Nov 20 '18 at 16:06
add a comment |
This is an interesting problem. One option if you want to keep linear time at the expense of some space it to make a lookup object based on id
. Then you can loop through those values and push into either a parent object or the array:
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
let lookup = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
let arr = Object.values(lookup).reduce((arr, val) =>{
if (val.parent_id == null) arr.push(val)
else (lookup[val.parent_id].children || ( lookup[val.parent_id].children = )).push(val)
return arr
}, )
console.log(JSON.stringify(arr, null, 2))
add a comment |
This is an interesting problem. One option if you want to keep linear time at the expense of some space it to make a lookup object based on id
. Then you can loop through those values and push into either a parent object or the array:
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
let lookup = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
let arr = Object.values(lookup).reduce((arr, val) =>{
if (val.parent_id == null) arr.push(val)
else (lookup[val.parent_id].children || ( lookup[val.parent_id].children = )).push(val)
return arr
}, )
console.log(JSON.stringify(arr, null, 2))
add a comment |
This is an interesting problem. One option if you want to keep linear time at the expense of some space it to make a lookup object based on id
. Then you can loop through those values and push into either a parent object or the array:
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
let lookup = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
let arr = Object.values(lookup).reduce((arr, val) =>{
if (val.parent_id == null) arr.push(val)
else (lookup[val.parent_id].children || ( lookup[val.parent_id].children = )).push(val)
return arr
}, )
console.log(JSON.stringify(arr, null, 2))
This is an interesting problem. One option if you want to keep linear time at the expense of some space it to make a lookup object based on id
. Then you can loop through those values and push into either a parent object or the array:
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
let lookup = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
let arr = Object.values(lookup).reduce((arr, val) =>{
if (val.parent_id == null) arr.push(val)
else (lookup[val.parent_id].children || ( lookup[val.parent_id].children = )).push(val)
return arr
}, )
console.log(JSON.stringify(arr, null, 2))
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
let lookup = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
let arr = Object.values(lookup).reduce((arr, val) =>{
if (val.parent_id == null) arr.push(val)
else (lookup[val.parent_id].children || ( lookup[val.parent_id].children = )).push(val)
return arr
}, )
console.log(JSON.stringify(arr, null, 2))
const data = [{id: 1, parent_id: null, name: 'test1'},{id: 2, parent_id: null, name: 'test2'},{id: 3, parent_id: 2, name: 'test3'},{id: 4, parent_id: 2, name: 'test4'},{id: 5, parent_id: 4, name: 'test5'},{id: 6, parent_id: 4, name: 'test5'},{id: 7, parent_id: 2, name: 'test5'},{id: 8, parent_id: 2, name: 'test5'},{id: 9, parent_id: null, name: 'test5'},{id: 10, parent_id: null, name: 'test5'},]
let lookup = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
let arr = Object.values(lookup).reduce((arr, val) =>{
if (val.parent_id == null) arr.push(val)
else (lookup[val.parent_id].children || ( lookup[val.parent_id].children = )).push(val)
return arr
}, )
console.log(JSON.stringify(arr, null, 2))
answered Nov 20 '18 at 15:56


Mark MeyerMark Meyer
38.1k33159
38.1k33159
add a comment |
add a comment |
you could try this recursive approach
const data = [{id: 1, parent_id: null, name: 'test1'}, {id: 2, parent_id: null, name: 'test2'}, {id: 3, parent_id: 2, name: 'test3'}, {id: 4, parent_id: 2, name: 'test4'}, {id: 5, parent_id: 4, name: 'test5'}, {id: 6, parent_id: 4, name: 'test5'}, {id: 7, parent_id: 2, name: 'test5'}, {id: 8, parent_id: 2, name: 'test5'}, {id: 9, parent_id: null, name: 'test5'}, {id: 10, parent_id: null, name: 'test5'}];
const transform = arr => {
return arr.reduce((acc, elem) => {
const children = data.filter(el => el.parent_id === elem.id),
isPresent = findDeep(acc, elem);
if(!isPresent && children.length)
acc.push({...elem, children: transform(children)});
else if(!isPresent)
acc.push(elem);
return acc;
}, );
}
const findDeep =(arr = , elem) => (
arr.some(el => (el.id === elem.id) || findDeep(el.children, elem))
);
console.log(transform(data));
add a comment |
you could try this recursive approach
const data = [{id: 1, parent_id: null, name: 'test1'}, {id: 2, parent_id: null, name: 'test2'}, {id: 3, parent_id: 2, name: 'test3'}, {id: 4, parent_id: 2, name: 'test4'}, {id: 5, parent_id: 4, name: 'test5'}, {id: 6, parent_id: 4, name: 'test5'}, {id: 7, parent_id: 2, name: 'test5'}, {id: 8, parent_id: 2, name: 'test5'}, {id: 9, parent_id: null, name: 'test5'}, {id: 10, parent_id: null, name: 'test5'}];
const transform = arr => {
return arr.reduce((acc, elem) => {
const children = data.filter(el => el.parent_id === elem.id),
isPresent = findDeep(acc, elem);
if(!isPresent && children.length)
acc.push({...elem, children: transform(children)});
else if(!isPresent)
acc.push(elem);
return acc;
}, );
}
const findDeep =(arr = , elem) => (
arr.some(el => (el.id === elem.id) || findDeep(el.children, elem))
);
console.log(transform(data));
add a comment |
you could try this recursive approach
const data = [{id: 1, parent_id: null, name: 'test1'}, {id: 2, parent_id: null, name: 'test2'}, {id: 3, parent_id: 2, name: 'test3'}, {id: 4, parent_id: 2, name: 'test4'}, {id: 5, parent_id: 4, name: 'test5'}, {id: 6, parent_id: 4, name: 'test5'}, {id: 7, parent_id: 2, name: 'test5'}, {id: 8, parent_id: 2, name: 'test5'}, {id: 9, parent_id: null, name: 'test5'}, {id: 10, parent_id: null, name: 'test5'}];
const transform = arr => {
return arr.reduce((acc, elem) => {
const children = data.filter(el => el.parent_id === elem.id),
isPresent = findDeep(acc, elem);
if(!isPresent && children.length)
acc.push({...elem, children: transform(children)});
else if(!isPresent)
acc.push(elem);
return acc;
}, );
}
const findDeep =(arr = , elem) => (
arr.some(el => (el.id === elem.id) || findDeep(el.children, elem))
);
console.log(transform(data));
you could try this recursive approach
const data = [{id: 1, parent_id: null, name: 'test1'}, {id: 2, parent_id: null, name: 'test2'}, {id: 3, parent_id: 2, name: 'test3'}, {id: 4, parent_id: 2, name: 'test4'}, {id: 5, parent_id: 4, name: 'test5'}, {id: 6, parent_id: 4, name: 'test5'}, {id: 7, parent_id: 2, name: 'test5'}, {id: 8, parent_id: 2, name: 'test5'}, {id: 9, parent_id: null, name: 'test5'}, {id: 10, parent_id: null, name: 'test5'}];
const transform = arr => {
return arr.reduce((acc, elem) => {
const children = data.filter(el => el.parent_id === elem.id),
isPresent = findDeep(acc, elem);
if(!isPresent && children.length)
acc.push({...elem, children: transform(children)});
else if(!isPresent)
acc.push(elem);
return acc;
}, );
}
const findDeep =(arr = , elem) => (
arr.some(el => (el.id === elem.id) || findDeep(el.children, elem))
);
console.log(transform(data));
const data = [{id: 1, parent_id: null, name: 'test1'}, {id: 2, parent_id: null, name: 'test2'}, {id: 3, parent_id: 2, name: 'test3'}, {id: 4, parent_id: 2, name: 'test4'}, {id: 5, parent_id: 4, name: 'test5'}, {id: 6, parent_id: 4, name: 'test5'}, {id: 7, parent_id: 2, name: 'test5'}, {id: 8, parent_id: 2, name: 'test5'}, {id: 9, parent_id: null, name: 'test5'}, {id: 10, parent_id: null, name: 'test5'}];
const transform = arr => {
return arr.reduce((acc, elem) => {
const children = data.filter(el => el.parent_id === elem.id),
isPresent = findDeep(acc, elem);
if(!isPresent && children.length)
acc.push({...elem, children: transform(children)});
else if(!isPresent)
acc.push(elem);
return acc;
}, );
}
const findDeep =(arr = , elem) => (
arr.some(el => (el.id === elem.id) || findDeep(el.children, elem))
);
console.log(transform(data));
const data = [{id: 1, parent_id: null, name: 'test1'}, {id: 2, parent_id: null, name: 'test2'}, {id: 3, parent_id: 2, name: 'test3'}, {id: 4, parent_id: 2, name: 'test4'}, {id: 5, parent_id: 4, name: 'test5'}, {id: 6, parent_id: 4, name: 'test5'}, {id: 7, parent_id: 2, name: 'test5'}, {id: 8, parent_id: 2, name: 'test5'}, {id: 9, parent_id: null, name: 'test5'}, {id: 10, parent_id: null, name: 'test5'}];
const transform = arr => {
return arr.reduce((acc, elem) => {
const children = data.filter(el => el.parent_id === elem.id),
isPresent = findDeep(acc, elem);
if(!isPresent && children.length)
acc.push({...elem, children: transform(children)});
else if(!isPresent)
acc.push(elem);
return acc;
}, );
}
const findDeep =(arr = , elem) => (
arr.some(el => (el.id === elem.id) || findDeep(el.children, elem))
);
console.log(transform(data));
edited Nov 20 '18 at 17:07
answered Nov 20 '18 at 16:05


KarimKarim
5,0691720
5,0691720
add a comment |
add a comment |
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
const output = data.filter(
item => !item.parent_id
).map(
rootItem => ({
...rootItem,
children: data.filter(item => item.parent_id === rootItem.id),
})
)
console.log(output)
1
What happened it id: 5?
– Mark Meyer
Nov 20 '18 at 15:37
Ah you're right there is more than one level of nesting, the best answer is probably the one using reduce.
– alexjackson
Nov 20 '18 at 15:39
add a comment |
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
const output = data.filter(
item => !item.parent_id
).map(
rootItem => ({
...rootItem,
children: data.filter(item => item.parent_id === rootItem.id),
})
)
console.log(output)
1
What happened it id: 5?
– Mark Meyer
Nov 20 '18 at 15:37
Ah you're right there is more than one level of nesting, the best answer is probably the one using reduce.
– alexjackson
Nov 20 '18 at 15:39
add a comment |
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
const output = data.filter(
item => !item.parent_id
).map(
rootItem => ({
...rootItem,
children: data.filter(item => item.parent_id === rootItem.id),
})
)
console.log(output)
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
const output = data.filter(
item => !item.parent_id
).map(
rootItem => ({
...rootItem,
children: data.filter(item => item.parent_id === rootItem.id),
})
)
console.log(output)
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
const output = data.filter(
item => !item.parent_id
).map(
rootItem => ({
...rootItem,
children: data.filter(item => item.parent_id === rootItem.id),
})
)
console.log(output)
const data = [
{id: 1, parent_id: null, name: 'test1'},
{id: 2, parent_id: null, name: 'test2'},
{id: 3, parent_id: 2, name: 'test3'},
{id: 4, parent_id: 2, name: 'test4'},
{id: 5, parent_id: 4, name: 'test5'},
{id: 6, parent_id: 4, name: 'test5'},
{id: 7, parent_id: 2, name: 'test5'},
{id: 8, parent_id: 2, name: 'test5'},
{id: 9, parent_id: null, name: 'test5'},
{id: 10, parent_id: null, name: 'test5'},
]
const output = data.filter(
item => !item.parent_id
).map(
rootItem => ({
...rootItem,
children: data.filter(item => item.parent_id === rootItem.id),
})
)
console.log(output)
answered Nov 20 '18 at 15:35
alexjacksonalexjackson
221
221
1
What happened it id: 5?
– Mark Meyer
Nov 20 '18 at 15:37
Ah you're right there is more than one level of nesting, the best answer is probably the one using reduce.
– alexjackson
Nov 20 '18 at 15:39
add a comment |
1
What happened it id: 5?
– Mark Meyer
Nov 20 '18 at 15:37
Ah you're right there is more than one level of nesting, the best answer is probably the one using reduce.
– alexjackson
Nov 20 '18 at 15:39
1
1
What happened it id: 5?
– Mark Meyer
Nov 20 '18 at 15:37
What happened it id: 5?
– Mark Meyer
Nov 20 '18 at 15:37
Ah you're right there is more than one level of nesting, the best answer is probably the one using reduce.
– alexjackson
Nov 20 '18 at 15:39
Ah you're right there is more than one level of nesting, the best answer is probably the one using reduce.
– alexjackson
Nov 20 '18 at 15:39
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.
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%2f53396194%2fcreate-nested-array-data-from-an-array-of-objects%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