0

I have an array that has parent-child values. I need to remove the elements from the array if its parent is already there in the array.

Sample data:

const data = [
  {
    id: "1",
    parentIds: []
  },
  {
    id: "2",
    parentIds: []
  },
  {
    id: "3",
    parentIds: ["1"]
  },
  {
    id: "4",
    parentIds: ["1", "3"]
  },
  {
    id: "5",
    parentIds: ["6"]
  }
]

The expected output is:

[
  {
    id: "1",
    parentIds: []
  },
  {
    id: "2",
    parentIds: []
  },
  {
    id: "5",
    parentIds: ["6"]
  }
]

I tried with the following code:

for (let i = selectedItems.length - 1; i >= 0; i--) {
      for (let j = selectedItems.length - 1; j >= 0; j--) {
        if (selectedItems[j].parentsIds.includes(selectedItems[i].id)) {
          selectedItems.splice(i, 1)
        }
      }
    }

But this fails with Cannot read properties of undefined (reading 'id') after splicing first match.

It there anyway this can be achieved?

codingenious
  • 8,385
  • 12
  • 60
  • 90
  • What if only *some* of its parents are there? Should it be removed? e.g. if there was `parentIds: ["1", "6"]`. "1" exists but "6" does not. What happens in that case? – Wyck Sep 26 '22 at 14:58
  • @Wyck: The expected output covers that... – Cerbrus Sep 26 '22 at 14:59
  • @Cerbrus, no it doesn't. All of the excluded items had either all of its parentIds not present or all of its parentIds present. There was no example with a mix. – Wyck Sep 26 '22 at 15:00
  • Ah okay.... Well, I'd assume that _"if its parent is already there in the array."_ means _any_ parent Id. – Cerbrus Sep 26 '22 at 15:02
  • Yeah, any parent id would result in removal. – codingenious Sep 26 '22 at 15:05

3 Answers3

2

First get an array of all id's using map().

Then use filter() to remove those where some() does not includes() in allIds

let data = [{id: "1", parentIds: [] }, {id: "2", parentIds: [] }, {id: "3", parentIds: ["1"] }, {id: "4", parentIds: ["1", "3"] }, {id: "5", parentIds: ["6"] } ];

const allIds = data.map(d => d.id);

data = data.filter((d, x) => !d.parentIds.some(a => allIds.includes(a)));

console.log(data);
0stone0
  • 34,288
  • 4
  • 39
  • 64
1

You need to .filter your data, to remove all items where .some of the parentIds are found in your data:

const data = [
  { id: "1", parentIds: [] },
  { id: "2", parentIds: [] },
  { id: "3", parentIds: ["1"] },
  { id: "4", parentIds: ["1", "3"] },
  { id: "5", parentIds: ["6"] }
];

const result = data.filter(
  row => !row.parentIds.some(
    id => data.some(d => d.id === id)
  )
);
      
console.log(result);
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
0

First extract an array of ids in the original array:

const ids = data.map(el => el.id)

Then filter the original array intersecting each element's parents array with the extracted ids array:

data.filter(el => el.parentIds.filter(parentId => ids.includes(parentId)).length === 0);

See this question Simplest code for array intersection in javascript for an explanation of how array intersection works.

gsim
  • 128
  • 7