在嵌套对象数组的最深层进行搜索,返回找到的对象的整棵树

问题描述 投票:0回答:1

JSON:https://api.jsonserve.com/SiEw5B

在此示例中,数据有 3 层,但可能更多

所以我可以做这样的事情来找到实际的对象

function findNode (id, array) {
    for (const node of array) {
    if(node.id===id)return node;    
    if (node.children) {
         const child = findNode(id, node.children);
            if(child) return child
                 
      }
    }
  }

但这不是我想要的,因为我希望为找到的对象返回整个树

所以我想到了创建一个临时数组,递归地将所有数组添加到其中,并且只保留那些隐藏了目标对象的数组

但问题是,无论我如何尝试解决它,我最终都会多出 4 个 for 循环,这是所有映射、过滤等的原因..

有没有简单的方法可以解决这个问题

因此,如果搜索“test-child-1”,我会喜欢最终结果

{
    id: '1',
    name: 'test-parent',
    children: [
        {
            id: '1a',
            name: 'test',
            children: [
                {
                    id: '1a1',
                    name: 'test-child-1',
                    children: null,
                }]
        }
    ]

}

有没有一种简单的方法来做到这一点,或者仅通过进行一堆 array.push、过滤、映射等操作并占用大量内存等?

javascript arrays for-loop recursion search
1个回答
1
投票

我认为这是一个相当简单的解决方案:

修复了评论中的问题

const findDeep = (pred) => (xs) => {
  for (let x of xs) {
    if (pred (x)) {return [x]}
    const c = findDeep(pred) (x.children || [])
    if (c) return [{...x, children: c}]
  }
}

const findDeepById = (target) => findDeep (x => x .id == target)

const data = [{"id":"1","name":"test-parent","children":[{"id":"1a","name":"test","children":[{"id":"1a1","name":"test-child-1","children":null},{"id":"1a2","name":"test-child-2","children":null},{"id":"1a3","name":"test-child-3","children":null}]},{"id":"1b","name":"test2","children":[{"id":"1b1","name":"test2-child-1","children":null}]}]},{"id":"2","name":"test-2-parent","children":[{"id":"2a","name":"test-2","children":[{"id":"2a1","name":"test-2-child-1","children":null}]}]}]

console .log (findDeepById ('1a1') (data))
.as-console-wrapper {max-height: 100% !important; top: 0}

旧版本:

const findDeep = (pred) => (xs) => {
  for (let x of xs) {
    if (pred (x)) {return [x]}
    const c = findDeep(pred) (x.children || [])
    if (c) return [{...x, children: [c]}]
  }
}

const findDeepById = (target) => findDeep (x => x .id == target)

const data = [{"id":"1","name":"test-parent","children":[{"id":"1a","name":"test","children":[{"id":"1a1","name":"test-child-1","children":null},{"id":"1a2","name":"test-child-2","children":null},{"id":"1a3","name":"test-child-3","children":null}]},{"id":"1b","name":"test2","children":[{"id":"1b1","name":"test2-child-1","children":null}]}]},{"id":"2","name":"test-2-parent","children":[{"id":"2a","name":"test-2","children":[{"id":"2a1","name":"test-2-child-1","children":null}]}]}]

console .log (findDeepById ('1a1') (data))
.as-console-wrapper {max-height: 100% !important; top: 0}

findDeep
是通用的,使用任意谓词。我们创建
findDeepById
作为一个函数,它接受
target
并传递给
findDeep
一个测试对象是否具有匹配的
id
的函数。然后我们在我们的数据上调用它。

主要功能应该很明显了。我们循环遍历提供的数组中的项目。如果我们当前的测试项与谓词匹配,我们将其包装在一个数组中并返回它。否则,我们会重复使用我们项目的子项。如果我们在那里找到结果,我们就会用一个包含该结果的新

children
数组包装当前对象。如果我们一路通过,我们将不会返回任何东西。

这不是我一贯的风格。我知道我在使用纯表达式而不是陈述之前也做过类似的问题,但我似乎把它们放错了地方,而且我的大脑现在还不够好,无法弄清楚。

关于这个:

有没有一种简单的方法来做到这一点,或者仅通过进行一堆 array.push、过滤、映射等操作并占用大量内存等?

首先,为什么你认为这些操作是内存密集型的?这个解决方案应该没问题。有两个局部变量,我们只构建我们实际需要返回的输出对象。如果递归深度是个问题,您可能需要重新考虑您的输入数据。

© www.soinside.com 2019 - 2024. All rights reserved.