Skip to content Skip to sidebar Skip to footer

Remove Item Recusively From Tree

I'm trying to create a tree component. But I dont know how remove a item recursively inside a tree. Each item its created dinamically and I would like remove an item/branch of the

Solution 1:

Although this can be done in a single function, it's a lot cleaner and less repetitive if you write this with mutual recursion. Here we write two functions. One removes the element from an array, replacing it with any children it might have. The other processes a single object, removing the id from it (and from any of its children.) Our main function here is removeElement, which will call removeElementFromArray on our input if the initial data is an array or call it against any children if the initial data is a plain object.

constremoveElementFromArray = (arr, id) =>
  arr .flatMap (
    o => o.id === id
      ? [... (o .children || []).map (o => removeElement (o, id))]
      : [removeElement (o, id)]
  )

constremoveElement = (obj, id) => 
  Array .isArray (obj)
    ? removeElementFromArray (obj, id)
    : {... obj, ... (obj .children ? {children: removeElementFromArray (obj .children, id)} : {}) }


const data = [
  {id: 1, title: 'foo', children: [
    {id: 11, title: 'bar'},
    {id: 12, title: 'baz', children: [
      {id: 121, title: 'qux'},
      {id: 122, title: 'quz'}
    ]},
    {id: 13, title: 'corge'}
  ]},
  {id: 2, title: 'grault'}
];

console .log (removeElement (data, 121)) // 121 removedconsole .log (removeElement (data, 12))  // 12 removed; 121 and 122 moved to 1console .log (removeElement (data, 1))   // 1 removed; 11, 12, 13 moved to rootconsole .log (removeElement (data, 42))  // No change
.as-console-wrapper {min-height: 100%!important; top: 0}

Solution 2:

Hope this will help

const data = [
  {
    id: 1,
    title: "foo",
    children: [
      { id: 11, parentId: 1, title: "bar" },
      {
        id: 12,
        parentId: 1,
        title: "baz",
        children: [
          { id: 121, parentId: 12, title: "qux" },
          { id: 122, parentId: 12, title: "quz" },
        ],
      },
      { id: 13, parentId: 1, title: "corge" },
    ],
  },
  { id: 2, title: "grault" },
];

const id = 12;

functionremoveElement(data, id) {
  return data
    .filter((dt) => {
      return dt.id !== id;
    })
    .map((dt) => {
      if (dt.children) {
        return {
          ...dt,
          children: removeElement(dt.children, id),
        };
      }
      return dt;
    });
}
console.log(removeElement(data, id));

Solution 3:

I agree with Scott that mutual recursion is a great fit for this problem. I would divide the responsibilities slightly different however -

constremove = (t = [], id = 0) =>
  t.flatMap(v =>remove1(v, id))

constremove1 = ({ children = [], ...t }, id = 0) => // "remove one"
  t.id === id
    ? remove(children, id)
    : [ { ...t, children: remove(children, id) } ]

const data = [
  {id: 1, title: 'foo', children: [
    {id: 11, title: 'bar'},
    {id: 12, title: 'baz', children: [
      {id: 121, title: 'qux'},
      {id: 122, title: 'quz'}
    ]},
    {id: 13, title: 'corge'}
  ]},
  {id: 2, title: 'grault'}
];

console.log(remove(data, 121))
console.log(remove(data, 12))
console.log(remove(data, 1))
console.log(remove(data, 42))
.as-console-wrapper {min-height: 100%!important; top: 0}

In addition, this answer cares less about the optional children property and as a result it will add { ...t, children: [] } to any t without children.


I admire Scott for his exacting approach and I wondered how I might be able to preserve the children-less leaf nodes -

constidentity = x => x

constupdate = (t = {}, k = "", f = identity) => // <- immutable update
  t[k] == null
    ? t
    : { ...t, [k]: f(t[k]) }

constremove = (t = [], id = 0) =>
  t.flatMap(v =>remove1(v, id))

constremove1 = (t = {}, id = 0) => 
  t.id === id
    ? remove(t.children, id)
    : [ update(t, "children", c =>remove(c, id)) ] // <-- updateconst data = [
  {id: 1, title: 'foo', children: [
    {id: 11, title: 'bar'},
    {id: 12, title: 'baz', children: [
      {id: 121, title: 'qux'},
      {id: 122, title: 'quz'}
    ]},
    {id: 13, title: 'corge'}
  ]},
  {id: 2, title: 'grault'}
];

console.log(remove(data, 121))
console.log(remove(data, 12))
console.log(remove(data, 1))
console.log(remove(data, 42))
.as-console-wrapper {min-height: 100%!important; top: 0}

Post a Comment for "Remove Item Recusively From Tree"