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、过滤、映射等操作并占用大量内存等?
我认为这是一个相当简单的解决方案:
(修复了评论中的问题)
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、过滤、映射等操作并占用大量内存等?
首先,为什么你认为这些操作是内存密集型的?这个解决方案应该没问题。有两个局部变量,我们只构建我们实际需要返回的输出对象。如果递归深度是个问题,您可能需要重新考虑您的输入数据。