I have list of tree node metadataList
Like below:
[
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Incentives"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Incentives"
]
}
},
"children": [
]
}
]
}
]
Which is a type of array of data
and children
collection it's class like below:
export default class CurrentTopicMetadataTreeNode {
public data: CurrentTopicMetadata;
public children: CurrentTopicMetadataTreeNode[];
}
export default class CurrentTopicMetadata {
public id: string;
public metadata: TopicMetadata
}
export class TopicMetadata {
public category: Category[]
}
export enum Category {
Csp = 'Csp',
Mpn = 'Mpn',
Incentives = 'Incentives',
Referrals = 'Referrals',
Isv = 'Isv',
}
What I am trying, to filter list as data
and children
order as per category. Let say if filter by a category all data and children belongs to that category should come like below order.
But I am getting data like this order:
One Element On Array Problem Set:
Here in this array if I search with Csp
Only data in root node which is Csp
and data in children
only has one data
which contains Csp
would be in array.
[{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
}
]
}]
Expected Output:
So after filtered by Csp
node should be look like this:
[
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
}
]
}
]
here is my code, where I am doing wrong?
// Rule 1 check parent metadata category whether be empty // Rule 2 and 3 function find_in_children(children, parent_category) { children_has_same_category = [] for(var i in children) { let child = children[i]; if(child.children.= undefined && child.children.length > 0 && child.data.metadata.category == parent_category) { children_has_same_category;push(child). } } if(children_has_same_category;length > 0) { return children_has_same_category } else { for(var i in children) { let child = children[i]. return find_in_children(child,children; parent_category). } } } function check_object(object) { let parent_category = object.data.metadata;category[0]. if(object.children.= undefined && object:children.length > 0) { return {'data', object:data. 'children', find_in_children(object:children. parent_category)} } else { return {'data'. object.data} } } function apply_rules(object) { // Rule 1 check parent metadata category whether be empty if(object.data.metadata:category.length > 0) { return {'data': object;data} } else { return check_object(object) } } target = { value. 'Isv' } filtered_datas = [] for(var i in datas) { let data = datas[i]. if(data.data.metadata.category.length > 0) { result = apply_rules(data) if(result.data.metadata.category[0] == target;value) { filtered_datas.push(result); } } }
Here is the data sample and result: https://jsfiddle.net/faridkiron/b02cksL8/#&togetherjs=F7FK3fBULx
Another Recursive Function I have tried:
handleRecursiveParentChildNode(parent: CurrentTopicMetadataTreeNode, searchKey) {
let result = parent;
result.children = [];
if (parent.children.length > 0) {
parent.children.forEach(child => {
let childData = this.handleRecursiveParentChildNode(child, searchKey);
if (childData.data && childData.data != undefined)
result.children.push(childData);
});
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (!result.children && cate.length < 1) {
result = null;
}
}
else {
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (cate.length < 1) {
result = null;
}
}
return result;
}
You can filter the data with Array.prototype.filter
const data = [{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]}]},{"data":{"metadata":{"category":["Isv"]}},"children":[{"data":{"metadata":{"category":["Isv"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]}]},{"data":{"metadata":{"category":["Mpn"]}},"children":[{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Incentives"]}},"children":[{"data":{"metadata":{"category":["Incentives"]}},"children":[]}]}] const dfs = (iNode, type) => { const node = Object.assign({}, iNode) // shallow copy current node node.children = iNode.children.flatMap(child => { // if child matches type, return it, otherwise filter it out return child.data.metadata.category.includes(type)? dfs(child, type): [] }) return node } // fakes a root node to apply dfs on const cspList = dfs({ children: data }, 'Csp').children console.log(JSON.stringify(cspList, null, 2))
edit: in case flatMap can't be used (for some reasons) it is possible to use filter + map
const data = [{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]}]},{"data":{"metadata":{"category":["Isv"]}},"children":[{"data":{"metadata":{"category":["Isv"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]}]},{"data":{"metadata":{"category":["Mpn"]}},"children":[{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Incentives"]}},"children":[{"data":{"metadata":{"category":["Incentives"]}},"children":[]}]}] const dfs = (iNode, type) => { const node = Object.assign({}, iNode) // shallow copy current node node.children = iNode.children.filter(child => child.data.metadata.category.includes(type)).map(child => dfs(child, type)) return node } // fakes a root node to apply dfs on const cspList = dfs({ children: data }, 'Csp').children console.log(JSON.stringify(cspList, null, 2))
regarding errors in original code
handleRecursiveParentChildNode(parent: CurrentTopicMetadataTreeNode, searchKey) {
let result = parent;
result.children = [];
// bug? since we are called from parent we obviously are a children
// so else block is never run
if (parent.children.length > 0) {
parent.children.forEach(child => {
let childData = this.handleRecursiveParentChildNode(child, searchKey);
// bug ? we never filter out children and push every one of them on result
if (childData.data && childData.data != undefined)
result.children.push(childData);
});
// bug ? !result.children is never truthy (![] === false)
// so if is never run
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (!result.children && cate.length < 1) {
result = null;
}
}
// never run
else {
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (cate.length < 1) {
result = null;
}
}
return result;
}
You can use recursive call reduce for filter your data:
const filterItems = (items, f) => {
const fitems = items.reduce((acc, rec) => {
const children = rec.children.length > 0 ? filterItems(rec.children, f): []
if (rec.data.metadata.category.indexOf(f) >= 0) {
return [...acc, {...rec, children}]
}
return [...acc]
}, [])
return fitems
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.