Remove Item Recusively From Tree
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"