2

i've got array like this. Unlimited number of nesting possible

const myArray = [
  {
   id: 1, 
   children: [
              { 
                id: 3,
                children: []
              }
             ]
  },
  {
   id: 2, children: []
  }
]

Please, help me to remove any object by id and return new array without it.

6 Answers 6

8

The recursiveRemove function will recursively remove the elements from the array and return the new list.

The map function creates copy of the items in the array, you can remove the map if you do not need to retain the original array's sanity.

function recursiveRemove ( list, id ) {
    return list.map ( item => { return {...item} }).filter ( item => {
        if ( 'children' in item ) {
            item.children = recursiveRemove ( item.children, id );
        }
        return item.id !== id;
    });
}
const test1 = recursiveRemove ( myArray, 1);
const test2 = recursiveRemove ( myArray, 2);
const test3 = recursiveRemove ( myArray, 3);
Sign up to request clarification or add additional context in comments.

Comments

8

Using array methods and recursive function:

function fn(arr, id) {
  return arr
    .filter((el) => el.id !== id)
    .map((el) => {
      if (!el.children || !Array.isArray(el.children)) return el;
      el.children = fn(el.children, id);
      return el;
    });
}

const myArray = [
  {
    id: 1,
    children: [
      {
        id: 3,
        children: [],
      },
    ],
  },
  {
    id: 2,
    children: [],
  },
];

console.log(fn(myArray,1))
console.log(fn(myArray,2))
console.log(fn(myArray,3))

Comments

3
function removeFromArrayOfObj (array, idToRemove) {
  for (const [i, e] of array.entries()) {
    if (e.id === idToRemove) {
     array.splice(i, 1)
     continue
    }
   if (e.children) {
     removeFromArrayOfObj(e.children, idToRemove)
    }
 }
 return array
}

Comments

2

You could destructure the object and take id and children out of the object. Then get a new object with the rest of the former object and map the children.

const
    withoutId = ({ id, children, ...o }) => ({ ...o, children: children.map(withoutId) }),
    array = [{ id: 1, children: [{ id: 3, children: [] }] }, { id: 2, children: [] }],
    without = array.map(withoutId);

console.log(without);

1 Comment

The op asked: Please, help me to remove any object by id...
1

It makes sense to me to separate out the recursive traversal and filtering from the actual details of removing a certain id. So I would write a more generic filterDeep function which keeps only those objects where a predicate is true, recursing into children nodes.

Then we can supply a predicate to it that checks whether an item matches a specific id. Or rather, since we're removing those that match, our predicate actually checks whether our node doesn't match the id.

This is an implementation of that idea:

const filterDeep = (pred) => (xs) =>
  xs .flatMap (x => pred (x)
    ? [{... x, children: filterDeep (pred) (x .children || [])}] 
    : []
  )
  
const removeId = (id) =>  
  filterDeep (x => x.id !== id)

const myArray = [{id: 1, children: [{id: 3, children: []}]}, {id: 2, children: []}]

console .log (removeId (1) (myArray))
console .log (removeId (2) (myArray))
console .log (removeId (3) (myArray))
console .log (removeId (42) (myArray))
.as-console-wrapper {min-height: 100% !important; top: 0}

This will include a children node even if the original didn't have one. If we wanted to include it only if there was one to begin with we could change it to something like this:

const filterDeep = (pred) => (xs) =>
  xs .flatMap (x => pred (x) 
    ? [{
        ... x, 
        ... (x.children ? {children: filterDeep (pred) (x .children || [])} : {})
      }] 
    : []
  )

Or with a little more sophistication, we could choose to include a children node only when it's available in the parent and the results are non-empty. That's left as an exercise for the reader. :-)

1 Comment

perfect timing for this question to come along! and perfect answer to pair with it!
0

Ah, homework problems.

  • write 'kill_entries_with_id(child_array, id_to_kill)'. For each element of the child array, it should del the element if its id matches. Otherwise, it should recursively call itself with the element's children.
  • Note that you should walk the array backwards by index so you don't have to worry about deleting elements mucking up your loop. Consider list(range(10,-1,-1)

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.