Home > Software design >  Javascript recursive Item Remove doesnt work
Javascript recursive Item Remove doesnt work

Time:02-02

i have a array of json like that:

and this is my code to remove a specific item with all of its childs sub childs ...:

     const items = [
      {id: 1, name: 'Block', text: '', has_childs: true,  parent_id : null},
      {id: 2, name: 'Block', text: '', has_childs: true,  parent_id : 1},
      {id: 3, name: 'Block', text: '', has_childs: false,  parent_id : 1},
      {id: 4, name: 'Block', text: '', has_childs: true,  parent_id : 2},
      {id: 5, name: 'Block', text: '', has_childs: false,  parent_id : 2},
      {id: 6, name: 'Block', text: '', has_childs: false,  parent_id : 2},
      {id: 7, name: 'Block', text: '', has_childs: false,  parent_id : 4}
    ];
    
    function removeItem(item){
                    var index = items.findIndex(function (o) {
                        return o.id == item.id;
                    })
    
                    if (index !== -1) {
    
                        var hasOtherChilds = false;
                        items.forEach((i) => {
                            if(i.parent_id == item.parent_id)
                                hasOtherChilds = true;
                        });
    
                        
                        items.forEach((i)=> {
                            if(i.id == item.parent_id && !hasOtherChilds)
                                i.has_childs  = false;
                        } )
                        
                        if (items[index].has_childs == true) {
                            var items_to_remove = [];
                            items.forEach((i) => {
                                if (i.parent_id == item.id) {
                                    items.splice(index, 1);
                                    items_to_remove.push(i);
                                }
                            });
    
                        }else {
                           items.splice(index, 1);
                        }
                    }
    
                    if(items_to_remove)
                    items_to_remove.forEach((item) => {
                        removeItem(item);
                    });
        }
    
    
    console.log(items);
    
    removeItem(items[1]);
    
    console.log(items)

But for some reason, he is always only deleting the first child/subchild and the last child/subchild i have no idea why

CodePudding user response:

You can store the IDs to remove in array. So in each iteration in filter we check

if the id exists in array, if it does exist then we return false. if it does not exists then we check, if parentId exists in array, if it does then we push the id in array and return false. at last if both of above conditions are failed then we return true.

Check following snippet.

const items = [{
    id: 1,
    name: 'Block',
    text: '',
    has_childs: true,
    parent_id: null
  },
  {
    id: 2,
    name: 'Block',
    text: '',
    has_childs: true,
    parent_id: 1
  },
  {
    id: 3,
    name: 'Block',
    text: '',
    has_childs: true,
    parent_id: null
  },
  {
    id: 4,
    name: 'Block',
    text: '',
    has_childs: true,
    parent_id: 2
  },
  {
    id: 5,
    name: 'Block',
    text: '',
    has_childs: false,
    parent_id: 2
  },
  {
    id: 6,
    name: 'Block',
    text: '',
    has_childs: false,
    parent_id: 2
  },
  {
    id: 7,
    name: 'Block',
    text: '',
    has_childs: false,
    parent_id: 4
  }
];

function remove(arr, id) {
  const idToRemove = [id];
  return items
    .filter((item) => {
      if (idToRemove.includes(item.id))
        return false;
      if (idToRemove.includes(item.parent_id)) {
        idToRemove.push(item.id);
        return false;
      } else return true;
    });
}

const filteredItems = remove(items, 1);

filteredItems.forEach(item => console.log(item)); //verify the right ones are gone

Here is more on filter

CodePudding user response:

A solution that recursively deletes all children, then the original item itself. Note that the has_childs property is completely useless in this process.

let items = [
  {id: 1, name: 'Block', text: '', parent_id : null},
  {id: 2, name: 'Block', text: '', parent_id : 1},
  {id: 3, name: 'Block', text: '', parent_id : 1},
  {id: 4, name: 'Block', text: '', parent_id : 2},
  {id: 5, name: 'Block', text: '', parent_id : 2},
  {id: 6, name: 'Block', text: '', parent_id : 2},
  {id: 7, name: 'Block', text: '', parent_id : 4}
];

const removeItem = item => {

    // Selecting all children
    const children = items.filter(i => i.parent_id===item.id);

    for(let child of children){
        console.log(`Removing child ${child.id}`)
        removeItem(child) // Will recursively remove all of their children
    }

    // Removing the original item itself, after removing all its children recursively
    items = items.filter(i => i.id !== item.id)
}

removeItem({id: 2, name: 'Block', text: '', parent_id : 1})

console.log("Items are now =", items)

CodePudding user response:

Can you not have a simple function to just filter out the values? Based on the structure of the array you want to filter (it isn't nested), I don't see any need for recursion.

const items = [
  {id: 1, name: 'Block', text: '', has_childs: true,  parent_id : null},
  {id: 2, name: 'Block', text: '', has_childs: true,  parent_id : 1},
  {id: 3, name: 'Block', text: '', has_childs: true,  parent_id : 1},
  {id: 4, name: 'Block', text: '', has_childs: true,  parent_id : 2},
  {id: 5, name: 'Block', text: '', has_childs: false,  parent_id : 2},
  {id: 6, name: 'Block', text: '', has_childs: false,  parent_id : 2},
  {id: 7, name: 'Block', text: '', has_childs: false,  parent_id : 4}
];

function remove(arr, id) {    
    const removed = new Set([id]);

    return arr.filter(item => {
      if (removed.has(item.id)) {
          return false;
      }
      
      if (removed.has(item.parent_id)) {
          removed.add(item.id);
          return false;
      }
      
      return true;
    });
}

//suppose we want to remove id = 2 and all its progeny
const filteredItems = remove(items, 2);

filteredItems.forEach(item => console.log(item));


  •  Tags:  
  • Related