Recursive Function Returns Undefined Regardless Of Enough Return Statements
Solution 1:
forEach
returns undefined
, so
return node.forEach(el => {
return recurseFind(el, id);
});
will always return undefined
, no matter what the recursive calls find.
I'd use a for
loop instead, and if a match is found, return it:
let animals = [
{
name: "dogs",
id: 1,
children: [
{
name: "lessie",
id: 2
},
{
name: "bark-a-lot",
id: 3
}
]
},
{
name: "cats",
id: 4,
children: [
{
name: "meows-a-lot",
id: 5,
children: [
{
name: "meows-a-lot-in-the-morning",
id: 6
}
]
},
{
name: "whisk-ass",
id: 7
}
]
}
];
functionrecurseFind(node, id) {
if (Array.isArray(node)) {
for (const el of node) {
const result = recurseFind(el, id);
if (result) return result;
}
} else {
if (node.id === id) {
return node;
} elseif (node.children) {
for (const child of node.children) {
const result = recurseFind(child, id);
if (result) return result;
}
}
}
}
const found = recurseFind(animals, 6) || 'not found';
console.log("found", found);
Solution 2:
VLAZ and CertainPerformance already pointed out why your function wasn't working.
Here's an alternative technique that seems a little simpler to me:
constrecursiveFind = (pred) => (xs) => xs .reduce (
(r, x) => r != null ? r : pred (x) ? x : recursiveFind (pred) (x.children || []) || null,
null
)
constfindById = (id) => recursiveFind(x => x.id == id)
const animals = [{name: "dogs", id: 1, children: [{name: "lessie", id: 2}, {name: "bark-a-lot", id: 3}]}, {name: "cats", id: 4, children: [{name: "meows-a-lot", id: 5, children: [{ name: "meows-a-lot-in-the-morning", id: 6}]}, {name: "whisk-ass", id: 7}]}];
console .log (findById (3) (animals))
console .log (findById (4) (animals))
We start with a generic function that searches for objects nested this way by whether they match the supplied predicate function. Then we pass it the predicate x => x.id == id
to create a function that takes an id and then a list of values and finds the first value with matching ids in the list, or null
if none are found.
If you have absolutely no use for this recursiveFind
function, you can inline it into findById
like this:
constfindById = (id, xs) => xs .reduce (
(r, x) => r != null ? r : x.id == id ? x : findById (id, x.children || []) || null,
null
)
findById (3, animals)
But I actually would prefer to go in the other direction, and make it still more generic, using something like this:
constrecursiveFind = (pred, descend) => (xs) => xs .reduce (
(r, x) => r != null ? r : pred (x) ? x : recursiveFind (pred, descend) (descend (x) || []) || null,
null
)
constfindById = (id) => recursiveFind (x => x.id == id, x => x.children)
findById (3) (animals)
This version also parameterizes how we descend into the children of a node. In this case, we simply use x => x.children
, but it's easy to imagine using other properties or a more complex method.
In all of these, do note that the function processes all nodes of your nested array structure, even when we've already found a match. If we have, the first check (r != null
) skips ahead quickly, but if performance is critical, you might prefer a solution with explicit short-circuiting loops such as the one from CertainPerformance.
Post a Comment for "Recursive Function Returns Undefined Regardless Of Enough Return Statements"