1

I have array of objects like below. Here children element may deeply nested, it may contain other children element as well.

let response = [{
 id: 4321,
 name: 'Education',
 parentId: null,
 children: [{
 id: 1234,
 name: 'category1',
 parentId: 4321,
 children: [{
 id: 8327548,
 name: '001',
 parentId: 1234,
 }, {
 id: 8327549,
 name: '002',
 parentId: 1234,
 }],
 }, {
 id: 6786,
 name: 'Associations',
 parentId: 4321,
 }, {
 id: 8262439,
 name: 'category1',
 parentId: 4321,
 }, {
 id: 8245,
 name: 'Rights',
 parentId: 4321,
 children: [{
 id: 2447,
 name: 'Organizations',
 parentId: 8245,
 }, {
 id: 9525,
 name: 'Services',
 parentId: 8245,
 }, {
 id: 8448,
 name: 'Organizations',
 parentId: 8245,
 }],
 }, {
 id: 8262446,
 name: 'Women\'s Rights',
 parentId: 4321,
 }],
}, {
 id: 21610,
 name: 'Agriculture',
 parentId: null,
 children: [{
 id: 3302,
 name: 'categoryABC',
 parentId: 21610,
 children: [{
 id: 85379,
 name: 'categoryABC - General',
 parentId: 3302,
 }, {
 id: 85380,
 name: 'categoryABC Technology',
 parentId: 3302,
 }],
 }, {
 id: 8303,
 name: 'Fungicides',
 parentId: 21610,
 children: [{
 id: 8503,
 name: 'Fungicides - General',
 parentId: 8303,
 }],
 }],
}];

I want to make it flat array of objects but I want to add parent name (which parentId is null) to every objects inside that respective parent.

expected output:

[
 {
 id: 8327548,
 name: "001",
 parentId: 1234
 mainParent: "Education"
 }, {
 id: 8327549,
 name: "002",
 parentId: 1234,
 mainParent: "Agriculture"
 },
 // ...OTHER OBJECTS....
]

What I have done so far

function flat(array) {
 var result = [];
 array.forEach(function (a) {
 result.push(a);
 if (Array.isArray(a.children)) {
 result = result.concat(flat(a.children));
 delete a.children;
 }
 });
 return result;
}

It's giving the flat array of objects but I'm not able to add parent name property to every objects.

Can someone please help me?

Peter Seliger
13.5k3 gold badges31 silver badges45 bronze badges
asked Oct 19, 2021 at 12:39
2
  • Do you want mainParent to be the top-level parent only? And do you want the results to only be the lowest-level children (ie, the leaves of the tree) Commented Oct 19, 2021 at 12:45
  • @Jamiec Yes, exactly Commented Oct 19, 2021 at 12:46

4 Answers 4

4

You could take a recursive approach an handover the first found name as mainParent.

const
 flat = mainParent => o => o.children
 ? o.children.flatMap(flat(mainParent || o.name))
 : { ...o, mainParent },
 response = [{ id: 4321, name: "Education", parentId: null, children: [{ id: 1234, name: "category1", parentId: 4321, children: [{ id: 8327548, name: "001", parentId: 1234 }, { id: 8327549, name: "002", parentId: 1234 }] }, { id: 6786, name: "Associations", parentId: 4321 }, { id: 8262439, name: "category1", parentId: 4321 }, { id: 8245, name: "Rights", parentId: 4321, children: [{ id: 2447, name: "Organizations", parentId: 8245 }, { id: 9525, name: "Services", parentId: 8245 }, { id: 8448, name: "Organizations", parentId: 8245 }] }, { id: 8262446, name: "Women's Rights", parentId: 4321 }] }, { id: 21610, name: "Agriculture", parentId: null, children: [{ id: 3302, name: "categoryABC", parentId: 21610, children: [{ id: 85379, name: "categoryABC - General", parentId: 3302 }, { id: 85380, name: "categoryABC Technology", parentId: 3302 }] }, { id: 8303, name: "Fungicides", parentId: 21610, children: [{ id: 8503, name: "Fungicides - General", parentId: 8303 }] }] }],
 result = response.flatMap(flat());
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

answered Oct 19, 2021 at 12:58
Sign up to request clarification or add additional context in comments.

Comments

2

This is a fairly clean recursion, stopping when there are no children in the node. We capture the first name value found along the hierarchy and carry it through.

const flat = (xs, name = null) => 
 xs .flatMap (x => x .children 
 ? flat (x .children, name || x .name)
 : [{...x, mainParent: name}]
 )
const response = [{id: 4321, name: "Education", parentId: null, children: [{id: 1234, name: "category1", parentId: 4321, children: [{id: 8327548, name: "001", parentId: 1234}, {id: 8327549, name: "002", parentId: 1234}]}, {id: 6786, name: "Associations", parentId: 4321}, {id: 8262439, name: "category1", parentId: 4321}, {id: 8245, name: "Rights", parentId: 4321, children: [{id: 2447, name: "Organizations", parentId: 8245}, {id: 9525, name: "Services", parentId: 8245}, {id: 8448, name: "Organizations", parentId: 8245}]}, {id: 8262446, name: "Women's Rights", parentId: 4321}]}, {id: 21610, name: "Agriculture", parentId: null, children: [{id: 3302, name: "categoryABC", parentId: 21610, children: [{id: 85379, name: "categoryABC - General", parentId: 3302}, {id: 85380, name: "categoryABC Technology", parentId: 3302}]}, {id: 8303, name: "Fungicides", parentId: 21610, children: [{id: 8503, name: "Fungicides - General", parentId: 8303}]}]}]
console .log (flat (response))
.as-console-wrapper {max-height: 100% !important; top: 0}

answered Oct 19, 2021 at 13:02

Comments

0

Less obscure, but still fairly concise.

const response = [{ id: 4321, name: 'Education', parentId: null, children: [{ id: 1234, name: 'category1', parentId: 4321, children: [{ id: 8327548, name: '001', parentId: 1234 }, { id: 8327549, name: '002', parentId: 1234 }] }, { id: 6786, name: 'Associations', parentId: 4321 }, { id: 8262439, name: 'category1', parentId: 4321 }, { id: 8245, name: 'Rights', parentId: 4321, children: [{ id: 2447, name: 'Organizations', parentId: 8245 }, { id: 9525, name: 'Services', parentId: 8245 }, { id: 8448, name: 'Organizations', parentId: 8245 }] }, { id: 8262446, name: 'Women\'s Rights', parentId: 4321 }] }, { id: 21610, name: 'Agriculture', parentId: null, children: [{ id: 3302, name: 'categoryABC', parentId: 21610, children: [{ id: 85379, name: 'categoryABC - General', parentId: 3302 }, { id: 85380, name: 'categoryABC Technology', parentId: 3302 }] }, { id: 8303, name: 'Fungicides', parentId: 21610, children: [{ id: 8503, name: 'Fungicides - General', parentId: 8303 }] }] }];
function flatten(arr, mainParent = null) {
 if (!arr) return;
 let result = [];
 for (const obj of arr) {
 result.push(...(flatten(obj.children, mainParent ?? obj.name) ?? [{ ...obj, mainParent }]));
 }
 return result;
}
console.log(flatten(response));
.as-console-wrapper { max-height: 100% !important; top: 0; }

answered Oct 19, 2021 at 13:38

Comments

0

A possible solution could be based entirely on a single, though recursively implemented, reduce task, where the accumulating and recursively passed down object carries both information, the mainParent value and the recursively collected final result ...

function recursivelyReassambleAndCollectChildlessItems(
 { mainParent, result }, { children, ...item }
) {
 result = result.concat(children && children.reduce(
 recursivelyReassambleAndCollectChildlessItems, {
 // was:
 // mainParent: mainParent ?? item.name,
 /**
 * OP quote:
 * "... but I want to add parent name 
 * (which parentId is null) to every
 * objects inside that respective parent."
 */
 mainParent: item.parentId === null ? item.name : mainParent,
 result: [],
 }
 ).result || { mainParent, ...item });
 
 return { mainParent, result };
}
const response = [{
 id: 4321,
 name: 'Education',
 parentId: null,
 children: [{
 id: 1234,
 name: 'category1',
 parentId: 4321,
 children: [{
 id: 8327548,
 name: '001',
 parentId: 1234,
 }, {
 id: 8327549,
 name: '002',
 parentId: 1234,
 }],
 }, {
 id: 6786,
 name: 'Associations',
 parentId: 4321,
 }, {
 id: 8262439,
 name: 'category1',
 parentId: 4321,
 }, {
 id: 8245,
 name: 'Rights',
 parentId: 4321,
 children: [{
 id: 2447,
 name: 'Organizations',
 parentId: 8245,
 }, {
 id: 9525,
 name: 'Services',
 parentId: 8245,
 }, {
 id: 8448,
 name: 'Organizations',
 parentId: 8245,
 }],
 }, {
 id: 8262446,
 name: 'Women\'s Rights',
 parentId: 4321,
 }],
}, {
 id: 21610,
 name: 'Agriculture',
 parentId: null,
 children: [{
 id: 3302,
 name: 'categoryABC',
 parentId: 21610,
 children: [{
 id: 85379,
 name: 'categoryABC - General',
 parentId: 3302,
 }, {
 id: 85380,
 name: 'categoryABC Technology',
 parentId: 3302,
 }],
 }, {
 id: 8303,
 name: 'Fungicides',
 parentId: 21610,
 children: [{
 id: 8503,
 name: 'Fungicides - General',
 parentId: 8303,
 }],
 }],
}];
console.log(response
 .reduce(recursivelyReassambleAndCollectChildlessItems, { result: [] })
 .result
)
.as-console-wrapper { min-height: 100%!important; top: 0; }

answered Oct 19, 2021 at 13:31

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.