0

I have array of objects, each object must have key and title, but children is optional, and it can be nested, i can have children inside of children many times. I want to remove some object by provided key value (for example key 677). I tried with filter but i only remove first level. Also have tried recursion, but not sure if i did it right.

const data = [{
    key: '1',
    title: 'title 1',
    children: [{
      key: '098',
      title: 'hey',
      children: [{
        key: '677',
        title: 'child'
      }]
    }]
  },
  {
    key: '123',
    title: 'tile 111'
  },
  {
    key: '345',
    title: 'something'
  }
];

const rem = '677';

const del = (el) => {
  if (!el.children) {
    return el.key !== rem;
  } else {
    if (el.key !== rem) {
      del(el.children);
      return el;
    }
  }
};
const res = data.filter((el) => {
  return del(el);
});

console.log(res);

3
  • 1
    1. there is a syntax error with the first children - children is array right now. 2. post your desirable result. Commented Nov 2, 2020 at 16:08
  • Your top level children is an array of objects, so add curly braces Commented Nov 2, 2020 at 16:08
  • Have you tried any recursive solutions? Would also be nice if you posted the filter code that only worked on the first level. Commented Nov 2, 2020 at 16:12

3 Answers 3

1

I guess your existing solution is like

const data = [
  {
    key: '1',
    title: 'title 1',
    children: [{
      key: '098',
      title: 'hey',
      children: [{ key: '677', title: 'child'}]
    }]
  },
  { key: '123', title: 'tile 111' },
  { key: '345', title: 'something' }
];

function removeByKey(arr, removingKey){
  return arr.filter( a => a.key !== removingKey);
}

So it works on the first level but not deeply.

Just change it like that will do the jobs

function removeByKey(arr, removingKey){
  return arr.filter( a => a.key !== removingKey).map( e => {
    return { ...e, children: removeByKey(e.children || [], removingKey)}
  });
}

Little warning, children property will not be set to [] for every item not having any children.

So how it works? Well instead of keeping acceptable items as they are, we make a copy using {...e} that's equivalent to {key:e.key, title:e.title, children:e.children} in this case.

We know force to override the property children with removeByKey(e.children || [], removingKey), so we call the method recursively. Not the function works deeeply.

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

Comments

1

I would use a recursion approach with findIndex and splice. Using some will allow the code to exit without running through the entire tree.

const data = [{
    key: '1',
    title: 'title 1',
    children: [{
      key: '098',
      title: 'hey',
      children: [{
        key: '677',
        title: 'child'
      }]
    }]
  },
  {
    key: '123',
    title: 'tile 111'
  },
  {
    key: '345',
    title: 'something'
  }
];

const removeKey = (data, key) => {
  // look to see if object exists
  const index = data.findIndex(x => x.key === key);
  if (index > -1) {
    data.splice(index, 1); // remove the object
    return true
  } else {
    // loop over the indexes of the array until we find one with the key
    return data.some(x => {
      if (x.children) {
        return removeKey(x.children, key);
      } else {
        return false;
      }
    })
  }
}

console.log(removeKey(data, '677'))
console.log(JSON.stringify(data));

2 Comments

there couldn't a data with index similar to a different child in a different index of it's ancestor?
I have no clue what you are asking.
0

You can use some simple recursion to do the trick:

const data = [
  {
    key: '1',
    title: 'title 1',
    children: [
     {
      key: '098',
      title: 'hey',
      children: [{ key: '677', title: 'child'}]
     }
    ]
  },
  { key: '123', title: 'tile 111' },
  { key: '345', title: 'something' }
];

function removeByKey(key, arr) {
  // loop through all items of array
  for(let i = 0; i < arr.length; i++) {
    // if array item has said key, then remove it
    if(arr[i].key === key) {
      arr.splice(i, 1);
    } else if(typeof(arr[i].children) !== "undefined") {
      // if object doesn't have desired key but has children, call this function 
      // on the children array
      removeByKey(key, arr[i].children);
    }
  }
}

removeByKey('098', data);

console.log(data);

This may be a little easier to understand than the other answer provided.

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.