【发布时间】:2021-01-15 11:16:05
【问题描述】:
我有一个包含多个对象(孩子和父母)的平面数组。每个对象都包含一个 id、一个 parentId 和第三个值作为“conditionId”。
我要做的是根据conditionId过滤数组,然后找到父母,父母的父母,然后是那些父母等等,直到我到达“根级别”。
我已经有一个递归函数可以做到这一点:
function findParents (directory, children) {
// creating an empty array to push the matching entities into
const entityArray = []
// looping through every entity in the directory
for (const entity of directory) {
// looping through every child of the children-array
for (const child of children) {
// checking if the parentId is not 0 and if the id of the entity matches the parentId of the child
if (child.parentId !== 0 && entity.id === child.parentId) {
// pushing the found entity to entityArray
entityArray.push(entity)
}
}
}
let recursiveResult = []
if (entityArray.length > 0) {
// calling the function
recursiveResult = findParents(directory, entityArray)
}
// returning the entityArray plus the result of the recursive call of this function
const result = entityArray.concat(recursiveResult)
return result
}
唯一的问题是,如果数组中的任何元素具有相同的父元素,则该父元素会被多次找到,我想避免这种情况,因为这意味着可以通过简单地检查这些元素是否可以避免不必要的操作已经找到了。
应该发生的事情的例子:
平面数组:
const myArr = [
{
id: '1',
parentId: '0',
conditionId: 'apple'
},
{
id: '2',
parentId: '1',
conditionId: 'apple'
},
{
id: '3',
parentId: '2',
conditionId: 'banana'
},
{
id: '4',
parentId: '2',
conditionId: 'banana'
},
{
id: '5',
parentId: '2',
conditionId: 'apple'
},
{
id: '6',
parentId: '2',
conditionId: 'apple'
}
]
通过 conditionId 找到的孩子:
const foundByCondition = [
{
id: '3',
parentId: '2',
conditionId: 'banana'
},
{
id: '4',
parentId: '2',
conditionId: 'banana'
},
]
在第一个函数调用中,将 myArr 和 foundByCondition 作为参数传递。
结果应该是这样的:
result: [
{
id: '1',
parentId: '0',
conditionId: 'apple'
},
{
id: '2',
parentId: '1',
conditionId: 'apple'
}
]
但实际上是这样的:
result: [
{
id: '1',
parentId: '0',
conditionId: 'apple'
},
{
id: '2',
parentId: '1',
conditionId: 'apple'
},
{
id: '2',
parentId: '1',
conditionId: 'apple'
}
]
我尝试添加一个 if 语句来检查该元素是否已经被找到一次:
const entityArray: object[] = []
// looping through every entity in the directory
for (const entity of directory) {
// checking if entityArray already contains entity of the loop
if (!entityArray.some(item => item.id === entity.id)) {
// looping through every child of the children-array
for (const child of children) {
// checking if the parentId is not 0 and if the id of the entity matches the parentId of the child
if (child.parentId !== 0 && entity.id === child.parentId) {
// pushing the found entity to entityArray
entityArray.push(entity)
}
}
}
}
}
但它每次都返回true。
【问题讨论】:
-
你能改变对象吗?只需通过存储父引用来记忆函数。
-
你的意思是只存储 parentIds 而不是整个父对象?
-
也许我误解了这个问题。我以为您想优化递归调用,这可能通过记忆化(实际上,与您目前拥有的算法不同)是可能的。但是,如果您当前正在寻找的只是为了防止结果中出现重复,那么更简单的解决方案是只将
entityArray设为new Set而不是数组。
标签: javascript recursion