Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed last year.
Improve this question
I have this array with two object, and I have another array with these IDs: [9054,9021,9040,8941,8947]. I want to filter the big array and get a new array with only matched IDs on the second array.
The problem is to get the same configuration of the array, I want just to delete the unmatched IDs. Any idea how to solve it?
const data =
[ { key: 9054, title: '22', children:
[ { key: 8959, title: 'ABR_ADRESSE', idFather: 8959, tableIsFamily: false, children: [] }
, { key: 8943, title: 'ABR_CONTACT', idFather: 8943, tableIsFamily: false, children: [] }
, { key: 9021, title: 'ABR_POSTE', idFather: 9021, tableIsFamily: false, children: [] }
, { key: 8969, title: 'ABR_SOCIETE', idFather: 8969, tableIsFamily: false, children: [] }
] }
, { key: 9040, title: '33', children:
[ { key: 8957, title: 'THB_Adresse_Famille', idFather: 8957, tableIsFamily: false, children: [] }
, { key: 8941, title: 'THB_Contact_Famille', idFather: 8941, tableIsFamily: false, children:
[ { key: 8947, title: 'THB_Contact_Table', idFather: 8941 }
, { key: 9855, title: 'THB_Contact_Table_BIS', idFather: 8941 }
] }
, { key: 8949, title: 'THB_Societe_Famille', idFather: 8949, tableIsFamily: false, children: [] }
, { key: 8983, title: 'THB_TELEPHONE', idFather: 8983, tableIsFamily: false, children: [] }
, { key: 10070, title: 'THB_TEST_5708', idFather: 10070, tableIsFamily: false, children: [] }
] } ]
The expected Output should be :
const data =
[ { key: 9054, title: '22', children:
[
, { key: 9021, title: 'ABR_POSTE', idFather: 9021, tableIsFamily: false, children: [] }
] }
, { key: 9040, title: '33', children:
[
, { key: 8941, title: 'THB_Contact_Famille', idFather: 8941, tableIsFamily: false, children:
[ { key: 8947, title: 'THB_Contact_Table', idFather: 8941 }
] }
] } ]
Is this your expected output?
[
{"key": 9054,"title": "22","children": [
{"key": 9021,"title": "ABR_POSTE","idFather": 9021,"tableIsFamily": false,"children": []}
]},
{"key": 9040,"title": "33","children": [
{"key": 8941,"title": "THB_Contact_Famille","idFather": 8941,"tableIsFamily": false,"children": [
{"key": 8947,"title": "THB_Contact_Table","idFather": 8941}
]}
]}
]
You will need to loop over each child and recursively filter the children and check if the sub-child key exists within the keys array.
const
data = [
{"key":9054,"title":"22","children":[
{"key":8959,"title":"ABR_ADRESSE","idFather":8959,"tableIsFamily":false,"children":[]},
{"key":8943,"title":"ABR_CONTACT","idFather":8943,"tableIsFamily":false,"children":[]},
{"key":9021,"title":"ABR_POSTE","idFather":9021,"tableIsFamily":false,"children":[]},
{"key":8969,"title":"ABR_SOCIETE","idFather":8969,"tableIsFamily":false,"children":[]}]},
{"key":9040,"title":"33","children":[
{"key":8957,"title":"THB_Adresse_Famille","idFather":8957,"tableIsFamily":false,"children":[]},
{"key":8941,"title":"THB_Contact_Famille","idFather":8941,"tableIsFamily":false,"children":[
{"key":8947,"title":"THB_Contact_Table","idFather":8941},
{"key":9855,"title":"THB_Contact_Table_BIS","idFather":8941}
]},
{"key":8949,"title":"THB_Societe_Famille","idFather":8949,"tableIsFamily":false,"children":[]},
{"key":8983,"title":"THB_TELEPHONE","idFather":8983,"tableIsFamily":false,"children":[]},
{"key":10070,"title":"THB_TEST_5708","idFather":10070,"tableIsFamily":false,"children":[]}
]}
];
// Based on: https://stackoverflow.com/a/41312330/1762224
// For an in-place delete, see: https://stackoverflow.com/a/41312346/1762224
const filterTreeList = (data, opts) =>
data.filter(item => {
if (item[opts.childrenKey]) {
item[opts.childrenKey] = filterTreeList(item[opts.childrenKey], opts);
}
return opts.keys.includes(item[opts.itemKey]);
});
const result = filterTreeList(data, {
itemKey: 'key',
childrenKey: 'children',
keys: [9054, 9021, 9040, 8941, 8947]
});
console.log(result);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Related
This question already has answers here:
Tree structure to flat array Javascript
(2 answers)
Closed 12 months ago.
I want to get length of multidimentionnal array in JS :
This is my array :
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',
},
{
title: '0-0-0-1',
key: '0-0-0-1',
},
{
title: '0-0-0-2',
key: '0-0-0-2',
},
],
},
{
title: '0-0-1',
key: '0-0-1',
children: [
{
title: '0-0-1-0',
key: '0-0-1-0',
},
{
title: '0-0-1-1',
key: '0-0-1-1',
},
{
title: '0-0-1-2',
key: '0-0-1-2',
},
],
},
{
title: '0-0-2',
key: '0-0-2',
},
],
},
{
title: '0-1',
key: '0-1',
children: [
{
title: '0-1-0-0',
key: '0-1-0-0',
},
{
title: '0-1-0-1',
key: '0-1-0-1',
},
{
title: '0-1-0-2',
key: '0-1-0-2',
},
],
},
{
title: '0-2',
key: '0-2',
},
];
The output should be : 15
The idea is to map trough all elements and if they have an array child, get the lentgh of it
I'm sure that I will go for a récursive function but it seems to be tricky..
I did'nt found any solutions in internet, have you an idea please ?
Thank you
function getLengthOfTreeData(treeData) {
let size = { size: 0 }; // object because it needs to be passed by reference
return getSize(size, treeData).size;
}
function getSize(size, treeData) { // recursive function
if (treeData.length === 0) {
return size;
}
size.size += treeData.length;
for (let i = 0; i < treeData.length; i++) {
const data = treeData[i];
if (data.children) getSize(size, data.children);
}
return size;
}
console.log(getLengthOfTreeData(treeData));
I working on a react project using Antd and I want to be able to disable cheking childs of my Tree component, so I can check only parent.This is my code
I found that I can add checkable : false to my child but I must create a function that render me a new TreeData that I can use instead of my normal data so I've tried this :
const TreeData = (data) => {
data.map((category) => {
category.children.map((family) => {
family.children.map((table) => {
table.checkable = false;
});
});
});
};
But it return undefined when i'm console.log the data received..
So my question is : how to switch from this :
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"
},
{
title: "0-0-0-1",
key: "0-0-0-1"
},
{
title: "0-0-0-2",
key: "0-0-0-2"
}
]
},
{
title: "0-0-1",
key: "0-0-1",
children: [
{
title: "0-0-1-0",
key: "0-0-1-0"
},
{
title: "0-0-1-1",
key: "0-0-1-1"
},
{
title: "0-0-1-2",
key: "0-0-1-2"
}
]
},
{
title: "0-0-2",
key: "0-0-2"
}
]
},
{
title: "0-1",
key: "0-1",
children: [
{
title: "0-1-0-0",
key: "0-1-0-0"
},
{
title: "0-1-0-1",
key: "0-1-0-1"
},
{
title: "0-1-0-2",
key: "0-1-0-2"
}
]
},
{
title: "0-2",
key: "0-2"
}
];
To this :
const treeData = [
{
title: "0-0",
key: "0-0",
children: [
{
checkable: false,
title: "0-0-0",
key: "0-0-0",
children: [
{
title: "0-0-0-0",
key: "0-0-0-0"
},
{
title: "0-0-0-1",
key: "0-0-0-1"
},
{
title: "0-0-0-2",
key: "0-0-0-2"
}
]
},
{
checkable: false,
title: "0-0-1",
key: "0-0-1",
children: [
{
title: "0-0-1-0",
key: "0-0-1-0"
},
{
title: "0-0-1-1",
key: "0-0-1-1"
},
{
title: "0-0-1-2",
key: "0-0-1-2"
}
]
},
{
checkable: false,
title: "0-0-2",
key: "0-0-2"
}
]
},
{
title: "0-1",
key: "0-1",
children: [
{
checkable: false,
title: "0-1-0-0",
key: "0-1-0-0"
},
{
checkable: false,
title: "0-1-0-1",
key: "0-1-0-1"
},
{
checkable: false,
title: "0-1-0-2",
key: "0-1-0-2"
}
]
},
{
title: "0-2",
key: "0-2"
}
];
Without hardchanging the first data of my Tree.
Thank you
This may be one possible implementation to set checkable as false for the specific nodes described in this question:
const makeUnCheckable = dataArr => (
dataArr.map(
obj => ({
...obj,
children: obj?.children?.map(cObj => ({
...cObj,
checkable: false
}))
})
)
);
return (
<Tree
checkable
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onCheck={onCheck}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={makeUnCheckable(treeData)}
/>
);
This is the result displayed on Codesandbox:
NOTES:
The elements showing as checked are clicked manually.
There is no check option for nodes 0-0-0, 0-0-1, 0-0-2, 0-1-0-0, 0-1-0-1, 0-1-0-2 - which is the expected objective defined in the question under To this
EDITED:
On perusing this previous question it seems like OP requires something like this:
(A tree where leaf nodes are uncheckable)
This may be achieved by a recursive method - something like this:
(Changes are present in: Lines 100 to 106. And line 118.)
EDITED - 2
Update based on comments below.
In order to identify the children for any given parent/key, something like the below may be useful:
Two methods are here. One is findKey which is recursive and gets the object which has a particular key (say 0-0-1). The other is to check if the object with the key has any children and if yes, return the children array.
I have a nested Object array and I would like to remove an item out of this nested array, but for some reason this does not seem to work with my approach:
Object
export const completeNavigationItemsV2Response = [
{
id: 'Erlebniskategorien',
title: 'Erlebniskategorien',
uri: '/on/demandware.store/Sites-JSShop-Site/default/SearchJS-Show',
children: [
{
id: 'fliegen-fallen',
title: 'Fallen & Springen',
uri: '/fliegen-fallen/fallen-springen,default,sc.html',
children: [
{
id: 'fallen-springen',
title: 'Fallen & Springen',
uri: '/fliegen-fallen/fallen-springen,default,sc.html',
children: [],
}
],
},
{
id: 'Weit-Weg',
title: 'Reisen & Kurzurlaub',
uri: '/reisen/Weit-Weg,default,sc.html',
children: [
{
id: 'staedtereisen',
title: 'Städtereisen',
uri: '/reisen/staedtereisen,default,sc.html',
children: [],
}
],
},
{
id: 'motorpower',
title: 'Motorpower',
uri: '/geschenke-maenner/motorpower,default,sc.html',
children: [
{
id: 'rennwagen',
title: 'Rennwagen',
uri: '/motorpower/rennwagen,default,sc.html',
children: [],
}
],
},
{
id: '10',
title: 'Erlebnisse mit Stars',
uri: '/erlebnisse-mit-stars/l/10',
children: [
{ // <== remove this object with id === 'glossar'
id: 'glossar',
title: 'Glossar',
uri: '/erlebnisstandorte/glossar,default,pg.html',
children: [],
},
],
},
],
}
];
Does someone of you would now a handy es6 way how to remove that subObject from the whole object in a somewhat dynamic way like with the .map() or .filter() function?
If you want it for any level in your object, you could do it with a recursive function like so:
// Object is the same, just minified
const completeNavigationItemsV2Response=[{id:"Erlebniskategorien",title:"Erlebniskategorien",uri:"/on/demandware.store/Sites-JSShop-Site/default/SearchJS-Show",children:[{id:"fliegen-fallen",title:"Fallen & Springen",uri:"/fliegen-fallen/fallen-springen,default,sc.html",children:[{id:"fallen-springen",title:"Fallen & Springen",uri:"/fliegen-fallen/fallen-springen,default,sc.html",children:[]}]},{id:"Weit-Weg",title:"Reisen & Kurzurlaub",uri:"/reisen/Weit-Weg,default,sc.html",children:[{id:"staedtereisen",title:"Städtereisen",uri:"/reisen/staedtereisen,default,sc.html",children:[]}]},{id:"motorpower",title:"Motorpower",uri:"/geschenke-maenner/motorpower,default,sc.html",children:[{id:"rennwagen",title:"Rennwagen",uri:"/motorpower/rennwagen,default,sc.html",children:[]}]},{id:"10",title:"Erlebnisse mit Stars",uri:"/erlebnisse-mit-stars/l/10",children:[{id:"glossar",title:"Glossar",uri:"/erlebnisstandorte/glossar,default,pg.html",children:[]}]}]}];
const removeItemWithId = (array, id) => {
return array
.filter(obj => obj.id !== id) // filter out if the id matches
.map(obj => ({ // Do the same for children (if they exist)
...obj,
children: obj.children !== undefined
? removeItemWithId(obj.children, id)
: undefined
}));
};
console.log(removeItemWithId(completeNavigationItemsV2Response, 'glossar'));
Although newer than ES6, if you can support .flatMap(), you can do this recursively by calling .flatMap() on your initial array and then calling it on your children array. If you reach the element which you want to remove, you can return an empty array [], which will remove the object when concatenated into the resulting array.
const arr = [{ id: 'Erlebniskategorien', title: 'Erlebniskategorien', uri: '/on/demandware.store/Sites-JSShop-Site/default/SearchJS-Show', children: [{ id: 'fliegen-fallen', title: 'Fallen & Springen', uri: '/fliegen-fallen/fallen-springen,default,sc.html', children: [{ id: 'fallen-springen', title: 'Fallen & Springen', uri: '/fliegen-fallen/fallen-springen,default,sc.html', children: [], }], }, { id: 'Weit-Weg', title: 'Reisen & Kurzurlaub', uri: '/reisen/Weit-Weg,default,sc.html', children: [{ id: 'staedtereisen', title: 'Städtereisen', uri: '/reisen/staedtereisen,default,sc.html', children: [], }], }, { id: 'motorpower', title: 'Motorpower', uri: '/geschenke-maenner/motorpower,default,sc.html', children: [{ id: 'rennwagen', title: 'Rennwagen', uri: '/motorpower/rennwagen,default,sc.html', children: [], }], }, { id: '10', title: 'Erlebnisse mit Stars', uri: '/erlebnisse-mit-stars/l/10', children: [{ id: 'glossar', title: 'Glossar', uri: '/erlebnisstandorte/glossar,default,pg.html', children: [], }, ], }, ], }];
const removeId = "glossar";
const res = arr.flatMap(function fn(o) {
return o.id !== removeId ? ({...o, children: o.children.flatMap(fn)}) : [];
});
console.log(res);
I'm trying to filter a nested structure, based on a search string.
If the search string is matched in an item, then I want to keep that item in the structure, along with its parents.
If the search string is not found, and the item has no children, it can be discounted.
I've got some code working which uses a recursive array filter to check the children of each item:
const data = {
id: '0.1',
children: [
{
children: [],
id: '1.1'
},
{
id: '1.2',
children: [
{
children: [],
id: '2.1'
},
{
id: '2.2',
children: [
{
id: '3.1',
children: []
},
{
id: '3.2',
children: []
},
{
id: '3.3',
children: []
}
]
},
{
children: [],
id: '2.3'
}
]
}
]
};
const searchString = '3.3';
const filterChildren = (item) => {
if (item.children.length) {
item.children = item.children.filter(filterChildren);
return item.children.length;
}
return item.id.includes(searchString);
};
data.children = data.children.filter(filterChildren);
console.log(data);
/*This outputs:
{
"id": "0.1",
"children": [
{
"id": "1.2",
"children": [
{
"id": "2.2",
"children": [
{
"id": "3.3",
"children": []
}
]
}
]
}
]
}*/
I'm concerned that if my data structure becomes massive, this won't be very efficient.
Can this be achieved in a 'nicer' way, that limits the amount of looping going on? I'm thinking probably using a reducer/transducer or something similarly exciting :)
A nonmutating version with a search for a child.
function find(array, id) {
var child,
result = array.find(o => o.id === id || (child = find(o.children, id)));
return child
? Object.assign({}, result, { children: [child] })
: result;
}
const
data = { id: '0.1', children: [{ children: [], id: '1.1' }, { id: '1.2', children: [{ children: [], id: '2.1' }, { id: '2.2', children: [{ id: '3.1', children: [] }, { id: '3.2', children: [] }, { id: '3.3', children: [] }] }, { children: [], id: '2.3' }] }] },
searchString = '3.3',
result = find([data], searchString);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here is where my algorithm skills ends. I can traverse through the object and find a certain object but I'm not able to delete the object in the same time.
Here is the object
const obj = {
children: [{
children: [
{
children: [
{
key: 'a1',
type: 'a1_type'
},
{
key: 'a2',
type: 'a2_type'
}
],
key: 'root',
type: 'root_type'
},
{
key: 'error',
type: 'error_type'
}
]
}]
}
The object with the key === 'error' object can be in any children array. I want to find it and delete the object that contains the key.
The output should be like that:
let output = findAndDeleteObjByKeyAndType('error', 'error_type')
output = {
children: [{
children: [
{
children: [
{
key: 'a1',
type: 'a1_type'
},
{
key: 'a2',
type: 'a2_type'
}
],
key: 'root',
type: 'root_type'
}
]
}]
}
Can someone help here?
Array methods like filter and every can come in handy here:
const object = {
children: [{
children: [{
children: [{
key: 'a1',
type: 'a1_type'
},
{
key: 'a2',
type: 'a2_type'
},
{
key: 'error',
type: 'error_type'
}
],
key: 'root',
type: 'root_type'
},
{
key: 'error',
type: 'error_type'
}
]
}]
}
function purgeAll (object, target) {
if (object.children) {
const keys = Object.keys(target)
object.children = object.children.filter(o =>
!keys.every(k => target[k] === o[k]) && purgeAll(o, target)
)
}
return object
}
let output = purgeAll(object, {
key: 'error',
type: 'error_type'
})
console.log(output)
.as-console-wrapper { min-height: 100%; }