Javascript group by array of objects (complicated objects) - javascript

After a lot of tries and search, I couldn't solve my following problem:
I have the following array
[
{text: "text", title: "title", cid: "cid", active: true, nodes: [
{title: "subTitle", text: "subText", cid: "cid", active: true, nodes: [
{text:"123", title:"321"},
{text:"456", title:"654"},
{text:"789", title:"765"}
]},
{title: "subTitle", text: "subText2", cid: "cid2", active: true, nodes: [
{text:"testText", title:"testTitle1"},
{text:"testText", title:"testTitle2"},
{text:"testText", title:"testTitle3"}
]},
{title: "subTitle", text: "subText3", cid: "cid3", active: true, nodes: [
{text:"ycycy", title:"asd"},
{text:"nyd", title:"yf"},
{text:"xfg", title:"qq"}
]},
{title: "anotherSubTitle", text: "subText4", cid: "cid4", active: true, nodes: [
{text:"fff", title:"hhh"},
{text:"xxx", title:"sss"},
{text:"hhh", title:"jjj"}
]}
]}
]
I want to reach the following format:
[
{text: "text", title: "title", cid: "cid", active: true, nodes: [
{title: "subTitle", text: "subText", cid: "cid", active: true, nodes: [
{text:"123", title:"321"},
{text:"456", title:"654"},
{text:"789", title:"765"},
{text:"testText", title:"testTitle1"},
{text:"testText", title:"testTitle1"},
{text:"testText", title:"testTitle1"},
{text:"ycycy", title:"asd"},
{text:"nyd", title:"yf"},
{text:"xfg", title:"qq"}
]},
{title: "anotherSubTitle", text: "subText4", cid: "cid4", active: true, nodes: [
{text:"fff", title:"hhh"},
{text:"xxx", title:"sss"},
{text:"hhh", title:"jjj"}
]}
]}
]
I tried array.reduce and to loop through the array but each time I got a wrong result...
Any suggestion plz?

You could take a nested grouping by a property for all levels.
const
groupBy = (array, key) => array.reduce((r, { nodes, ...o }) => {
let temp = r.find(q => q[key] === o[key]);
if (!temp) r.push(temp = o);
if (nodes) (temp.nodes ??= []).push(...groupBy(nodes, key));
return r;
}, []),
data = [{ text: "text", title: "title", cid: "cid", active: true, nodes: [{ title: "subTitle", text: "subText", cid: "cid", active: true, nodes: [{ text: "123", title: "321" }, { text: "456", title: "654" }, { text: "789", title: "765" }] }, { title: "subTitle", text: "subText2", cid: "cid2", active: true, nodes: [{ text: "testText", title: "testTitle1" }, { text: "testText", title: "testTitle2" }, { text: "testText", title: "testTitle3" }] }, { title: "subTitle", text: "subText3", cid: "cid3", active: true, nodes: [{ text: "ycycy", title: "asd" }, { text: "nyd", title: "yf" }, { text: "xfg", title: "qq" }] }] }],
result = groupBy(data, 'title');
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

I have 3 dx-selects they need to be related to each other

When I select the first selectbox, the other selectbox should also show its subcategories, but I couldn't do that. It says it's done with onValueChanged but I can't do it. I'm not very good at javascript how can I do this? When I did it with the normal html select option, I did it with the value value, but I can't do it with dx-select
<div class="Marka">
<div class="dx-field">
<h3>Marka</h3>
<div class="dx-field-value">
<div id="searchBox"></div>
</div>
</div>
$(() => {
const searchBox = $('#searchBox').dxSelectBox({
dataSource: products,
displayExpr: 'Name',
valueExpr: 'ID',
searchEnabled: true,
}).dxSelectBox('instance');
const productsDataSource = new DevExpress.data.DataSource({
store: {
data: simpleProducts,
type: 'array',
key: 'ID',
},
});
$('#editBox').dxSelectBox({
dataSource: productsDataSource,
displayExpr: 'Name',
valueExpr: 'ID',
value: simpleProducts[0].ID,
acceptCustomValue: true,
onValueChanged(data) {
const $result = $('.current-value');
if (data.value !== null) {
const selectedItem = data.component.option('selectedItem');
$result.text(`${selectedItem.Name} (ID: ${selectedItem.ID})`);
} else {
$result.text('Not selected');
}
},
onCustomItemCreating(data) {
if (!data.text) {
data.customItem = null;
return;
}
const productIds = simpleProducts.map((item) => item.ID);
const incrementedId = Math.max.apply(null, productIds) + 1;
const newItem = {
Name: data.text,
ID: incrementedId,
};
data.customItem = productsDataSource.store().insert(newItem)
.then(() => productsDataSource.load())
.then(() => newItem)
.catch((error) => {
throw error;
});
},
});
$('#searchModeOption').dxSelectBox({
items: ['contains', 'startswith'],
value: 'contains',
onValueChanged(e) {
searchBox.option('searchMode', e.value);
},
});
$('#searchExprOption').dxSelectBox({
items: [{
name: "'Name'",
value: 'Name',
}, {
name: "['Name', 'Category']",
value: ['Name', 'Category'],
}],
displayExpr: 'name',
valueExpr: 'value',
value: 'Name',
onValueChanged(e) {
searchBox.option('searchExpr', e.value);
},
});
$('#searchTimeoutOption').dxNumberBox({
min: 0,
max: 5000,
value: 200,
showSpinButtons: true,
step: 100,
onValueChanged(e) {
searchBox.option('searchTimeout', e.value);
},
});
$('#minSearchLengthOption').dxNumberBox({
min: 0,
max: 5,
value: 0,
showSpinButtons: true,
onValueChanged(e) {
searchBox.option('minSearchLength', e.value);
},
});
$('#showDataBeforeSearchOption').dxCheckBox({
value: false,
text: 'Show Data Before Search',
onValueChanged(e) {
searchBox.option('showDataBeforeSearch', e.value);
},
});
});
const simpleProducts = [
{ Name: 'Markalar', ID: 0 },
{ Name: 'Alfa Romeo', ID: 1 },
{ Name: 'Aston Martin', ID: 2 },
{ Name: 'Audi', ID: 3 },
{ Name: 'Bentley', ID: 4 },
{ Name: 'BMW', ID: 5 },
{ Name: 'Cadillac', ID: 6 },
{ Name: 'Chevrolet', ID: 7 },
{ Name: 'Chrysler', ID: 8 },
{ Name: 'Citroen', ID: 9 },
];
const products = [{
ID: 1,
Name: 'Alfa Romeo',
Price: 330,
Current_Inventory: 225,
Backorder: 0,
Manufacturing: 10,
Category: 'Marka',
ImageSrc: 'images/products/1.png'
}, {
ID: 2,
Name: 'Aston Martin',
Price: 400,
Current_Inventory: 150,
Backorder: 0,
Manufacturing: 25,
Category: 'Marka',
ImageSrc: 'images/products/2.png',
}, {
ID: 3,
Name: 'Audi',
Price: 2400,
Current_Inventory: 0,
Backorder: 0,
Manufacturing: 0,
Category: 'Marka',
ImageSrc: 'images/products/3.png',
}, {
ID: 4,
Name: 'Bentley',
Price: 1600,
Current_Inventory: 77,
Backorder: 0,
Manufacturing: 55,
Category: 'Televisions',
ImageSrc: 'images/products/4.png',
}, {
ID: 5,
Name: 'BMW',
Price: 1450,
Current_Inventory: 445,
Backorder: 0,
Manufacturing: 0,
Category: 'Televisions',
ImageSrc: 'images/products/5.png',
}, {
ID: 6,
Name: 'Cadillac',
Price: 1350,
Current_Inventory: 345,
Backorder: 0,
Manufacturing: 5,
Category: 'Televisions',
ImageSrc: 'images/products/6.png',
}
];
> type here
I solved the problem this site was very helpful
👇🏻
https://supportcenter.devexpress.com/ticket/details/e5000/selectboxes-for-devextreme-how-to-implement-standalone-and-in-form-cascading-selectboxes
enter<div class="arac dx-fieldset">
<div class="Marka">
<div class="dx-fieldset-header"></div>
<div class="dx-field">
<h3>Marka</h3>
<div class="dx-field-value">
<div id="markaSelectBox"></div>
</div>
</div>
</div>
<div class="Model">
<div class="dx-fieldset-header"></div>
<div class="dx-field">
<h3>Model</h3>
<div class="dx-field-value">
<div id="modelSelectBox"></div>
</div>
</div>
</div>
<div class="Parca">
<div class="dx-fieldset-header"></div>
<div class="dx-field">
<h3>Parça</h3>
<div class="dx-field-value">
<div id="parcaSelectBox"></div>
</div>
</div>
</div>
</div>
<script>
$(function(){
$("#markaSelectBox").dxSelectBox({
dataSource: markalar,
valueExpr: "ID",
displayExpr: "Name",
showClearButton: true,
searchEnabled: true,
onValueChanged: function(e) {
let dataSource = modelSelectBox.getDataSource();
dataSource.filter("MarkaID", "=", e.value);
dataSource.load();
modelSelectBox.option("value", null);
}
});
let modelSelectBox = $("#modelSelectBox").dxSelectBox({
dataSource: modeller,
valueExpr: "ID",
displayExpr: "Name",
searchEnabled: true,
}).dxSelectBox("instance");
$("#markaModelForm").dxForm({
FormData: toplam,
onFieldDataChanged: function(e){
if(e.dataField === "MarkaID"){
let modelEditor = e.component.getEditor("ModelID");
modelEditor.getDataSource().filter(['MarkaID', '=', e.value]);
modelEditor.getDataSource().load();
e.component.updateData("ModelID", null);
}
},
items:[
//marka itemi
{
label: {text: "Marka"},
dataField: "MarkaID",
editorType: "dxSelectBox",
editorOptions: {
dataSource: markalar,
valueExpr: "ID",
displayExpr: "Name",
showClearButton: true,
}
},
//model itemi
{
label: {text: "Model"},
dataField: "ModelID",
editorType: "dxSelectBox",
editorOptions: {
dataSource: modeller,
valueExpr: "ID",
displayExpr: "Name"
}
},
//model itemi
{
label: {text: "Parca"},
dataField: "ParcaID",
editorType: "dxSelectBox",
editorOptions: {
dataSource: parcalar,
valueExpr: "ID",
displayExpr: "Name"
}
}, //model itemi
{
label: {text: "Parca"},
dataField: "ParcaID",
editorType: "dxSelectBox",
editorOptions: {
dataSource: parcalar,
valueExpr: "ID",
displayExpr: "Name"
}
}
]
});
});
$(function(){
$("#modelSelectBox").dxSelectBox({
dataSource: modeller,
valueExpr: "ID",
displayExpr: "Name",
showClearButton: true,
searchEnabled: true,
onValueChanged: function(e) {
let dataSource = parcaSelectBox.getDataSource();
dataSource.filter("ModelID", "=", e.value);
dataSource.load();
parcaSelectBox.option("value", null);
}
});
let parcaSelectBox = $("#parcaSelectBox").dxSelectBox({
dataSource: parcalar,
valueExpr: "ID",
displayExpr: "Name",
searchEnabled: true,
}).dxSelectBox("instance");
$("#markaModelForm").dxForm({
FormData: toplam,
onFieldDataChanged: function(e){
if(e.dataField === "ModelID"){
let parcaEditor = e.component.getEditor("ParcaID");
parcaEditor.getDataSource().filter(['ModelID', '=', e.value]);
parcaEditor.getDataSource().load();
e.component.updateData("ParcaID", null);
}
},
});
});
var toplam = { MarkaID: null, ModelID: null, ParcaID: null }
var markalar = [
{ Name: 'Markalar', ID: 0 },
{ Name: 'Alfa Romeo', ID: 1 },
{ Name: 'Aston Martin', ID: 2 },
{ Name: 'Audi', ID: 3 },
{ Name: 'Bentley', ID: 4 },
{ Name: 'BMW', ID: 5 },
{ Name: 'Cadillac', ID: 6 },];
var modeller = [{
"ID":1,
"Name": "6",
"MarkaID": 1
},{
"ID":2,
"Name": "33",
"MarkaID": 1
},{
"ID":3,
"Name": "75",
"MarkaID": 1
},{
"ID":4,
"Name": "90",
"MarkaID": 1
}];
var parcalar = [{
"ID":1,
"Name": "Abs ve fren sensörleri",
"ModelID": 1
},{
"ID":2,
"Name": "El fren teli",
"ModelID": 1
},{
"ID":3,
"Name": "Fren aksesuar seti",
"ModelID": 1
},
{
"ID":4,
"Name": "Fren Balatası",
"ModelID": 1
},
]
</script>

How to get an objects out from very complex deeply nested array of objects and arrays?

My data structure is very complex, can't figure out how to map through the data in a way so I can get what I want. There's a very big array with a lot of objects in it and each object has again arrays and objects nested in each other. The data looks like this:
const arr1 = [
{
id: 1,
subject: 'Subject',
chapters: [
{
name: 'chapter1',
sections: [
{
name: 'section1',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
{
name: 'section2',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
],
},
{
name: 'chapter2',
sections: [
{
name: 'section1',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
{
name: 'section2',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
],
},
],
},
{
id: 2,
subject: 'Subject',
chapters: [
{
name: 'chapter1',
sections: [
{
name: 'section1',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
{
name: 'section2',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
],
},
{
name: 'chapter2',
sections: [
{
name: 'section1',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
{
name: 'section2',
questions: [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
],
},
],
},
],
},
];
How can I get an array from arr1 with only the objects located in 'questions' array, so it will look like this:
const arr2 = [
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
{
title: 'Title',
subtitle: 'SubTitle',
},
]
Use flatMap
const arr1 = [{id: 1,subject: 'Subject',chapters: [{name: 'chapter1',sections: [{name: 'section1',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},{name: 'section2',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},],},{name: 'chapter2',sections: [{name: 'section1',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},{name: 'section2',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},],},],},{id: 2,subject: 'Subject',chapters: [{name: 'chapter1',sections: [{name: 'section1',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},{name: 'section2',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},],},{name: 'chapter2',sections: [{name: 'section1',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},{name: 'section2',questions: [{title: 'Title',subtitle: 'SubTitle',},{title: 'Title',subtitle: 'SubTitle',},],},],},],},];
const result = arr1.flatMap(({chapters}) =>
chapters.flatMap(({sections}) =>
sections.flatMap(({questions}) => questions)
)
);
console.log(result);

manipulate nested array of objects to access children values

I have a nested array of objects:
const nestArray = [
{
title: "title 1",
children: [
{
title: "title 1-1",
children: [
{ title: "title 1-1-1", children: [...] },
{ title: "title 1-1-2", children: [...] }
]
},
{
title: "title 1-2",
children: [
{ title: "title 1-2-1", children: [...] },
{ title: "title 1-2-2", children: [...] }
]
},
]
},
{...},
{...}
]
All objects have the same interface:
interface Obj {
title: string
children: Obj[]
}
I need to put a new key into each object called keys.
The keys will keep all its children's titles alongside its own title. So the final result should be:
const nestArray = [
{
title: "title 1",
keys: ["title 1", "title 1-1", "title 1-1-1", "title 1-1-2"],
children: [
{
title: "title 1-1",
keys: ["title 1-1", "title 1-1-1", "title 1-1-2"],
children: [
{ title: "title 1-1-1", keys: ["title 1-1-1"], children: [] },
{ title: "title 1-1-2", keys: ["title 1-1-2"], children: [] }
]
},
{
title: "title 1-2",
keys: ["title 1-2", "title 1-2-1", "title 1-2-2"],
children: [
{ title: "title 1-2-1", keys: ["title 1-2-1"], children: [] },
{ title: "title 1-2-2", keys: ["title 1-2-2"], children: [] }
]
},
]
},
{...},
{...}
]
so the interface will be changed as:
interface Obj {
title: string
children: Obj[]
keys: string[]
}
I searched a lot but couldn't find any solution on the internet. I tried to solve this problem on my own, using recursive functions but still, I couldn't do it.
Using lodash is fine
What i've tried so far:
const mapTitlesToKeys = (obj) => {
obj.keys = [obj.title];
obj.children.forEach((childObj) => {
mapTitlesToKeys(childObj);
obj.keys.push(childObj.title);
});
};
nestArray.forEach((obj) => {
mapTitlesToKeys(obj);
});
console.log(nestArray);
results in:
[
{
title: "title 1",
keys: ['title 1', 'title 1-1', 'title 1-2'], // <-- should be ["title 1", "title 1-1", "title 1-1-1", "title 1-1-2"]
children: [
{
title: "title 1-1",
keys: ['title 1-1', 'title 1-1-1', 'title 1-1-2'], // <-- should be ["title 1-1", "title 1-1-1", "title 1-1-2"]
children: [
{
title: "title 1-1-1",
keys: ["title 1-1-1"], // <-- fine
children: []
},
{
title: "title 1-1-2",
keys: ["title 1-1-2"], // <-- fine
children: []
}
]
},
{
title: "title 1-2",
keys: ['title 1-2', 'title 1-2-1', 'title 1-2-2'], // <-- should be ["title 1-2", "title 1-2-1", "title 1-2-2"]
children: [
{
title: "title 1-2-1",
keys: ["title 1-2-1"], // <-- fine
children: []
},
{
title: "title 1-2-2",
keys: ["title 1-2-2"], // <-- fine
children: []
}
]
},
]
},
{...},
{...}
]
Presented below is one possible way to achieve the desired objective.
Code Snippet
const addKeysTo = arr => (
arr.map(
({ title, children }) => {
const cArr = addKeysTo(children);
keys = [title, ...cArr.flatMap(({ keys }) => keys )];
return ({ title, keys, children: cArr });
}
)
);
/* explanation of the method
// method to add "keys" array to each elt
const addKeysTo = arr => (
// use ".map()" to iterate over given array
arr.map(
// destructure to access "title", "children"
({ title, children }) => {
// recurse to obtain updated childre-narray
const cArr = addKeysTo(children);
// construct "keys" array for current elt
keys = [title, ...cArr.flatMap(({ keys }) => keys )];
// explicit return of current elt of "arr" array with "keys" prop
return ({ title, keys, children: cArr });
}
) // implicit return from the method
);
*/
const nestArray = [{
title: "title 1",
children: [{
title: "title 1-1",
children: [{
title: "title 1-1-1",
children: []
},
{
title: "title 1-1-2",
children: []
}
]
},
{
title: "title 1-2",
children: [{
title: "title 1-2-1",
children: []
},
{
title: "title 1-2-2",
children: []
}
]
},
]
}];
console.log(
'added keys to nested-objects array...\n',
addKeysTo(nestArray)
);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.
Something like this? (Shorter version... No need to keep the old one)
const nestArray = [{
title: "title 1",
children: [{
title: "title 1-1",
children: [{
title: "title 1-1-1",
children: []
},
{
title: "title 1-1-2",
children: []
}
]
},
{
title: "title 1-2",
children: [{
title: "title 1-2-1",
children: []
},
{
title: "title 1-2-2",
children: []
}
]
},
]
}]
function add_keys_obj(obj) {
obj.keys = [obj.title];
obj.children.forEach(function(child) {
add_keys_obj(child)
obj.keys.push(...child.keys)
})
}
function add_keys(arr) {
arr.forEach(function(obj, key) {
add_keys_obj(obj);
})
return arr;
}
add_keys(nestArray)
document.querySelector("pre").innerText = JSON.stringify(nestArray, null, 2);
<pre></pre>

how to flatten out the array and assign new keys? (TS, JS)

From this long JSON file, I want to pick few keys and values.
[{
c_id: "1",
c: "google",
displayName: "display name",
myResults: [{ //type: Array<MyResult>
type: 'TEXT',
name: 'my text',
label: 'my RealText',
id: '2',
description: 'sdf'
}, {
type: 'STRING',
name: 'my text',
label: 'my sdf',
id: '3',
description: 'sdf',
}
],
fieldValues: 'Object',
id: "d-ss-dd-asda-sdcv",
index: 0,
name: "google",
type: "NAH",
},
{
c_id: "sddc-ss",
connector: "facebook",
displayName: "d f d",
myFields: [],
myResults: [{ //type: Array<MyResult>
type: 'TEXT',
name: 'my text',
label: 'my RealText',
id: '5',
description: 'sdf'
}, {
type: 'STRING',
name: 'my text',
label: 'my sdf',
id: '6',
description: 'sdf',
}
],
fieldValues: 'Object',
id: "s-sdf-sdfdc",
index: 1,
name: "action",
type: "ACTION"
}];
Output
[{
id: "d-ss-dd-asda-sdcv", //c_id
label: 'google' //c
index: 0
}, {
id: '2',
label: 'my RealText',
}, {
id: '3',
label: 'my sdf',
}, {
id: "sddc-ss", //c_id
label: 'facebook' //c
index: 0
}, {
id: '5',
label: 'my RealText',
}, {
id: '6',
label: 'my sdf',
}]
How do I make this work using flatList?
input.flatMap(({ myResults, ...item }) => [item, ...myResults])
const result = data.flatMap(({ c_id, c, index, myResults }) => ([
{ id: c_id, label: c, index },
...myResults.map(({ id, label }) => ({ id, label }))
]))
Maybe this would work, but I'm just guessing because your data seems inconsistent. c_id and id seem to get switched, google is the "c" key but facebook is the "connector key"

create a pruned copy of tree in javascript

I'm trying to create a pruned version of the tree below where I have the source data/tree:
const treeData = [{
title: '0-0',
key: '0-0',
children: [{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0', children: [] },
{ title: '0-0-0-1', key: '0-0-0-1', children: [] },
{ title: '0-0-0-2', key: '0-0-0-2', children: [] },
],
}, {
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0', children: [] },
{ title: '0-0-1-1', key: '0-0-1-1', children: [] },
{ title: '0-0-1-2', key: '0-0-1-2', children: [] },
],
}, {
title: '0-0-2',
key: '0-0-2',
children: []
}],
}, {
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-1-0-0', children: [] },
{ title: '0-1-0-1', key: '0-1-0-1', children: [] },
{ title: '0-1-0-2', key: '0-1-0-2', children: [] },
],
}, {
title: '0-2',
key: '0-2',
children: []
}];
and an array of leaf nodes as inputs.
const leafNodes = ['0-0-1-2', '0-1-0-1', '0-1-0-2']
Given this input, I would want this pruned tree that uses the leaf nodes to build all paths from the root to each leaf:
const pruned [{
title: '0-0',
key: '0-0',
children: [{
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-2',
key: '0-0-1-2',
children: []
}
]
}]
}, {
title: '0-1',
key: '0-1',
children: [{
title: '0-1-0-1',
key: '0-1-0-1',
children: []
}, {
title: '0-1-0-2',
key: '0-1-0-2',
children: []
}]
}]
I was thinking of building the copy node by node instead of copying the data source and then taking away the paths not buildable based on the array/list of leaf nodes as I figured that would be the easiest to grok for maintainability purposes but even then, I'm puzzled as to how to coordinate the process, especially when accounting for the middle nodes that have already been added to my copy tree in progress as would be the case for '0-1-0-1' and '0-1-0-2'. At any rate, I've been stumped for awhile and threw my hands up. The code referenced is javascript but I'd be open to answers in other languages similar enough to javascript.
You could build new array/objects by finding the target key and collect all objects to it by returning the arrays with the necessary nodes.
function getParts(array, leafes) {
var result = [];
array.forEach(o => {
var children;
if (leafes.includes(o.key)) {
result.push(o);
return;
}
children = getParts(o.children, leafes);
if (children.length) {
result.push(Object.assign({}, o, { children }));
}
});
return result;
}
const
treeData = [{ title: '0-0', key: '0-0', children: [{ title: '0-0-0', key: '0-0-0', children: [{ title: '0-0-0-0', key: '0-0-0-0', children: [] }, { title: '0-0-0-1', key: '0-0-0-1', children: [] }, { title: '0-0-0-2', key: '0-0-0-2', children: [] }] }, { title: '0-0-1', key: '0-0-1', children: [{ title: '0-0-1-0', key: '0-0-1-0', children: [] }, { title: '0-0-1-1', key: '0-0-1-1', children: [] }, { title: '0-0-1-2', key: '0-0-1-2', children: [] }] }, { title: '0-0-2', key: '0-0-2', children: [] }] }, { title: '0-1', key: '0-1', children: [{ title: '0-1-0-0', key: '0-1-0-0', children: [] }, { title: '0-1-0-1', key: '0-1-0-1', children: [] }, { title: '0-1-0-2', key: '0-1-0-2', children: [] }] }, { title: '0-2', key: '0-2', children: [] }],
leafNodes = ['0-0-1-2', '0-1-0-1', '0-1-0-2'],
pruned = getParts(treeData, leafNodes);
console.log(pruned);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources