1

I have the following array of objects with nested elements in the children property. I need to get objects by their id if the id matches.

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

If no match on root element is found, the function should lookup its children to see if there is a match, and the first children match should be pushed on the root level.

For exemple, I have a list of ids: [12, 16787217, 16787245, 16787266]

The function should return only objects where ids matches while keeping hierarchy if matching parent id have matching children id, so it should 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": []
          }
        ]
      }
    ]
  }
]

As for now, I can get only the first level elements if they are found with this function:

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

Anyone have an idea on how to achieve this?

2
  • what, if you have a hole, for example not 16787245 inside the wanted ids? Commented Jun 8, 2021 at 8:25
  • 1
    It should have 16787266 just under 16787217 (in the children array) Commented Jun 8, 2021 at 8:29

2 Answers 2

1

You could reduce the array and take the nodes with found id and children or only the children at the base level.

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

Sign up to request clarification or add additional context in comments.

Comments

0

You could also try this

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.