按 属性 值递归过滤嵌套对象并保持数组结构

Filter nested objects by property value recursively and keep array structure

我在 children 属性 中有以下具有嵌套元素的对象数组。如果 ID 匹配,我需要通过 ID 获取对象。

[
  {
    "id": 10,
    "name": "Scenarios",
    "value": null,
    "children": [
      {
        "id": 12,
        "name": "Scenario status",
        "value": null,
        "children": []
      }
    ]
  },
  {
    "id": 11,
    "name": "Forecast source",
    "value": null,
    "children": []
  },
  {
    "id": 16787217,
    "name": "Item@Cust",
    "value": null,
    "children": [
      {
        "id": 16787230,
        "name": "Customer",
        "value": null,
        "children": [
          {
            "id": 16787265,
            "name": "Site",
            "value": null,
            "children": []
          },
          {
            "id": 16787291,
            "name": "Commercial Network",
            "value": null,
            "children": []
          },
          {
            "id": 16787296,
            "name": "Distribution Site",
            "value": null,
            "children": []
          }
        ]
      },
      {
        "id": 16787245,
        "name": "Item@Site",
        "value": null,
        "children": [
          {
            "id": 16787266,
            "name": "Family@Warehouse",
            "value": null,
            "children": []
          }
        ]
      },
      {
        "id": 16787254,
        "name": "Item",
        "value": null,
        "children": [
          {
            "id": 16787260,
            "name": "Family",
            "value": null,
            "children": [
              {
                "id": 16787264,
                "name": "Product line",
                "value": null,
                "children": []
              }
            ]
          },
          {
            "id": 16787261,
            "name": "Group 1",
            "value": null,
            "children": []
          }
        ]
      }
    ]
  },
  {
    "id": 16787267,
    "name": "Supplier",
    "value": null,
    "children": []
  },
  {
    "id": 16787297,
    "name": "SKU",
    "value": null,
    "children": []
  }
]

如果在根元素上找不到匹配项,该函数应查找其子元素以查看是否存在匹配项,并且应将第一个子元素匹配项推送到根级别。

例如,我有一个 ID 列表:[12, 16787217, 16787245, 16787266]

如果匹配的父 ID 具有匹配的子 ID,函数应该 return 只有 ID 匹配的对象,同时保持层次结构,所以它应该 return this:

[
  {
    "id": 12,
    "name": "Scenario status",
    "value": null,
    "children": []
  },
  {
    "id": 16787217,
    "name": "Item@Cust",
    "value": null,
    "children": [
      {
        "id": 16787245,
        "name": "Item@Site",
        "value": null,
        "children": [
          {
            "id": 16787266,
            "name": "Family@Warehouse",
            "value": null,
            "children": []
          }
        ]
      }
    ]
  }
]

至于现在,如果用这个函数找到第一级元素,我只能得到第一级元素:

filterArray(array: Array<any>, ids: Array<number>) {
        array = array.filter(el => ids.includes(el.id));
        for (let i = 0; i < array.length; i++) {
            this.filterArray(array[i].children, ids);
        }
        console.log(array);
    }

有人知道如何实现这个吗?

您可以减少数组并获取具有找到的 ID 和子节点的节点,或者仅获取基本级别的子节点。

const
    find = (r, { children = [], ...o }) => {
        children = children.reduce(find, []);
        if (ids.includes(o.id)) r.push({ ...o, children });
        else if (children.length) r.push(...children);
        return r;
    },
    data = [{ id: 10, name: "Scenarios", value: null, children: [{ id: 12, name: "Scenario status", value: null, children: [] }] }, { id: 11, name: "Forecast source", value: null, children: [] }, { id: 16787217, name: "Item@Cust", value: null, children: [{ id: 16787230, name: "Customer", value: null, children: [{ id: 16787265, name: "Site", value: null, children: [] }, { id: 16787291, name: "Commercial Network", value: null, children: [] }, { id: 16787296, name: "Distribution Site", value: null, children: [] }] }, { id: 16787245, name: "Item@Site", value: null, children: [{ id: 16787266, name: "Family@Warehouse", value: null, children: [] }] }, { id: 16787254, name: "Item", value: null, children: [{ id: 16787260, name: "Family", value: null, children: [{ id: 16787264, name: "Product line", value: null, children: [] }] }, { id: 16787261, name: "Group 1", value: null, children: [] }] }] }, { id: 16787267, name: "Supplier", value: null, children: [] }, { id: 16787297, name: "SKU", value: null, children: [] }],
    ids = [12, 16787217, 16787245, 16787266],
    result = data.reduce(find, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

你也可以试试这个

let data = [
  {
    "id": 10,
    "name": "Scenarios",
    "value": null,
    "children": [
      {
        "id": 12,
        "name": "Scenario status",
        "value": null,
        "children": []
      }
    ]
  },
  {
    "id": 11,
    "name": "Forecast source",
    "value": null,
    "children": []
  },
  {
    "id": 16787217,
    "name": "Item@Cust",
    "value": null,
    "children": [
      {
        "id": 16787230,
        "name": "Customer",
        "value": null,
        "children": [
          {
            "id": 16787265,
            "name": "Site",
            "value": null,
            "children": []
          },
          {
            "id": 16787291,
            "name": "Commercial Network",
            "value": null,
            "children": []
          },
          {
            "id": 16787296,
            "name": "Distribution Site",
            "value": null,
            "children": []
          }
        ]
      },
      {
        "id": 16787245,
        "name": "Item@Site",
        "value": null,
        "children": [
          {
            "id": 16787266,
            "name": "Family@Warehouse",
            "value": null,
            "children": []
          }
        ]
      },
      {
        "id": 16787254,
        "name": "Item",
        "value": null,
        "children": [
          {
            "id": 16787260,
            "name": "Family",
            "value": null,
            "children": [
              {
                "id": 16787264,
                "name": "Product line",
                "value": null,
                "children": []
              }
            ]
          },
          {
            "id": 16787261,
            "name": "Group 1",
            "value": null,
            "children": []
          }
        ]
      }
    ]
  },
  {
    "id": 16787267,
    "name": "Supplier",
    "value": null,
    "children": []
  },
  {
    "id": 16787297,
    "name": "SKU",
    "value": null,
    "children": []
  }
]

let ids = [12, 16787217, 16787245, 16787266]


let filterArray = (mArray, ids) => {
  let result = []
  for (const x of mArray) {
    if (ids.includes(x.id)) {
      let element = {...x, children: []}
      let childrenFounds = []
      if (x.children.length) {
        childrenFounds = filterArray(x.children, ids)
        if (childrenFounds.length) element.children.push(...childrenFounds)
      }else {
        delete element.children
      }
      result.push(element)
    } else if (x.children.length) {
      let found = filterArray(x.children, ids)
      if (found.length) result.push(...found)
    }
  }
  return result
}

let res = filterArray(data, ids)
console.log('res', res)