首页 > 解决方案 > 父子数组排序不起作用

问题描述

我有树节点列表metadataList如下:

   [
  {
    "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": [

        ]
      }
    ]
  }
]

这是一种数组类型,datachildren的类如下所示:

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',

}

我正在尝试按类别过滤列表data和排序。children假设如果按类别过滤所有数据和属于该类别的子项应该如下所示。

在此处输入图像描述

但我得到这样的数据:

在此处输入图像描述

One Element On Array Problem Set:

在这个数组中,如果我使用CspOnly data in root node which is搜索Csp并且数据中children只有一个data包含Csp将在数组中。

[{
    "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:所以按节点过滤后Csp应该是这样的:

[
  {
    "data": {
      "metadata": {
        "category": [
          "Csp"
        ]
      }
    },
    "children": [
      {
        "data": {
          "metadata": {
            "category": [
              "Csp"
            ]
          }
        },
        "children": [

        ]
      }
    ]
  }
]

这是我的代码,我在哪里做错了?

// 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);
        }
    }
}

这是数据样本和结果:https ://jsfiddle.net/faridkiron/b02cksL8/#&togetherjs=F7FK3fBULx

我尝试过的另一个递归函数:

   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;
    }

标签: javascripttypescript

解决方案


您可以使用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))

编辑:如果 flatMap 不能使用(由于某些原因),可以使用 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))


关于原始代码中的错误

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;
}

推荐阅读