简体   繁体   English

嵌套数组对象的递归函数返回未定义

[英]recursive function for nested array objects returns undefined

I'm trying to find/ extract a specific object in a nested hierarchy.我正在尝试在嵌套层次结构中查找/提取特定对象。 when the entity is found I console.log it and then return it.找到实体后,我将其 console.log 并返回。 the log is the correct object but the function still returns undefined.日志是正确的对象,但函数仍然返回未定义。

any solutions?任何解决方案? I've tried with a map, reduce, and a classic for loop and still gets undefined back.我已经尝试过 map、reduce 和经典的 for 循环,但仍然未定义。

 const hierarchy = { id: '1', title: 'root', children: [ { id: '2', title: 'second ab', children: [ { id:'999', title: 'nested child AB', children: [ { id:'88888', title: 'very nested child AB' } ], } ], }, { id: '3', title: 'third ab', children: [ { id:'444', title: 'nested child AB', children: [ { id:'5555', title: 'very nested child AB' } ], } ], } ] } const findEntityToAddInHierarchy = (entityArr, entityId) => { return entityArr.forEach(entity => { if(entity.id === entityId) { console.log('found and returning', entity) return entity; } else { return entity.children && findEntityToAddInHierarchy(entity.children, entityId) } }) } const result = findEntityToAddInHierarchy([hierarchy], '5555'); console.log('this returns undefined', result)

As imvrain2 already explained, there is an issue in your code with forEach .正如 imvrain2 已经解释的那样,您的forEach代码存在问题。 That answer is one way to solve this.该答案是解决此问题的一种方法。

But I believe we can write this more simply.但我相信我们可以更简单地写这个。 Here is a version that returns all matches in an array.这是一个返回数组中所有匹配项的版本。 If there are multiple values with the same id, they will all appear.如果有多个具有相同 id 的值,它们都会出现。 If there are none, it will be an empty array.如果没有,它将是一个空数组。 If you are using it with the certainty that three will always be exactly one, you can choose just to extract the first result from the list (although I suppose that might be wasteful.)如果您在使用它时确定三个始终是一个,您可以选择只从列表中提取第一个结果(尽管我认为这可能是浪费。)

 const matchById = (target) => (obj) => [ ... (obj.id === target ? [obj] : []), ... (obj .children || []) .flatMap (matchById (target)) ] const hierarchy = {id: '1', title: 'root', children: [{id: '2', title: 'second ab', children: [{id:'999', title: 'nested child AB', children: [{id:'88888', title: 'very nested child AB'}]}]}, {id: '3', title: 'third ab', children: [{id:'444', title: 'nested child AB', children: [{id:'5555', title: 'very nested child AB'}]}]}]} console .log (matchById ('5555') (hierarchy))

We return an array that starts with the current object (if it has the right id) and then simply recurs on each of its children, flattening into a single array.我们返回一个以当前对象开头的数组(如果它有正确的 id),然后简单地在它的每个子对象上递归,扁平化为一个数组。

With only a little more work, however, we can make this more generic, where we test each element with a predicate to decide if we want to accept it, and then use that to build our custom function:然而,只需要多做一点工作,我们就可以使它更通用,我们用一个谓词测试每个元素来决定我们是否要接受它,然后使用它来构建我们的自定义函数:

 const getMatches = (pred) => (obj) => [ ... (pred (obj) ? [obj] : []), ... (obj .children || []) .flatMap (getMatches (pred)) ] const matchById = (target) => getMatches (({id}) => id === target) const hierarchy = {id: '1', title: 'root', children: [{id: '2', title: 'second ab', children: [{id:'999', title: 'nested child AB', children: [{id:'88888', title: 'very nested child AB'}]}]}, {id: '3', title: 'third ab', children: [{id:'444', title: 'nested child AB', children: [{id:'5555', title: 'very nested child AB'}]}]}]} console .log (matchById ('5555') (hierarchy))

And now we can find all matches for any predicate we can define.现在我们可以找到我们可以定义的任何谓词的所有匹配项。 This is the version I would use.这是我会使用的版本。

I think generators are a particularly good fit for searching algorithms.我认为生成器特别适合搜索算法。 We can start by writing a generic preorder traversal which produces a flattened stream of objects.我们可以从编写一个通用的preorder遍历开始,它产生一个扁平的对象流。 Then writing searchById is a simple for..of construct -然后编写searchById是一个简单的for..of构造 -

 function* preorder (t = {}) { yield t if (t.children) for (const c of t.children) yield* preorder(c) } function searchById (t = {}, q = null) { for (const v of preorder(t)) if (v.id == q) return v return false } const input = {id: '1', title: 'root', children: [{id: '2', title: 'second ab', children: [{id:'999', title: 'nested child AB', children: [{id:'88888', title: 'very nested child AB'}]}]}, {id: '3', title: 'third ab', children: [{id:'444', title: 'nested child AB', children: [{id:'5555', title: 'very nested child AB'}]}]}]} const result = searchById(input, 5555) console.log(result)


{
  "id": "5555",
  "title": "very nested child AB"
}

If no result is found, false is returned -如果未找到结果,则返回false -

const result = 
  searchById(input, "Z")
  
console.log(result)
false

forEach doesn't return anything, so one solution is to set a variable instead. forEach 不返回任何内容,因此一种解决方案是设置一个变量。 Then return the variable instead.然后返回变量。

 const hierarchy = { id: '1', title: 'root', children: [ { id: '2', title: 'second ab', children: [ { id:'999', title: 'nested child AB', children: [ { id:'88888', title: 'very nested child AB' } ], } ], }, { id: '3', title: 'third ab', children: [ { id:'444', title: 'nested child AB', children: [ { id:'5555', title: 'very nested child AB' } ], } ], } ] } const findEntityToAddInHierarchy = (entityArr, entityId) => { _r = {}; entityArr.forEach(entity => { if(entity.id === entityId) { console.log('found and returning', entity) _r = entity; } else { _r = entity.children && findEntityToAddInHierarchy(entity.children, entityId) } }) return _r } const result = findEntityToAddInHierarchy([hierarchy], '5555'); console.log('this returns undefined', result)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM