简体   繁体   English

遍历JSON数据中的嵌套数组

[英]Traverse in nested arrays in JSON data

I have the data like this: 我有这样的数据:

    {
        {
            "text" : "parent1",
            "nodes" :[
                {
                    "text": "child1",
                    "nodes": [
                        {
                            "text": "grandchild1",
                            "nodes":[
                                {
                                    "text": "hello",
                                    "nodes": []
                                }
                            ]
                        },
                        {
                            "text": "hello",
                            "nodes":[]
                        }
                    ]
                }
            ]
        },
        {
            "text" : "parent2",
            "nodes" :[
                {
                    "text": "child2",
                    "nodes": [
                        {
                            "text": "grandchild2",
                            "nodes": [
                                {
                                    "text": "grandgrandchild1",
                                    "nodes": [
                                        {
                                            "text": "hello",
                                            "nodes": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]

                }
            ]
        }
    }

What I want is, creating a path array that contains the path of the elements whose "text" value is "hello". 我想要的是创建一个路径数组,其中包含“文本”值为“ hello”的元素的路径。 For example, according to this data: 例如,根据此数据:

var paths: any[][] = [
    ["parent1","child1","grandchild1","hello"],
    ["parent1","child1","hello"],
    ["parent2","child2","grandchild2","grandgrandchild1","hello"]
];

I want this "paths" array. 我想要这个“路径”数组。 Please notice, if the element's text value is "hello", then this element's "nodes" length is 0. I think I'm making a mistake in recursion. 请注意,如果元素的文本值为“ hello”,则该元素的“节点”长度为0。我认为我在递归中犯了一个错误。

You need to 你需要

  • Traverse the object using recursion, 使用递归遍历对象,
  • Assign paths along the way 沿途分配路径
  • and finally keep record those paths when the current text matches the text. 最后在当前文本与文本匹配时记录这些路径

Demo 演示版

 var obj = [{ "text": "parent1", "nodes": [{ "text": "child1", "nodes": [{ "text": "grandchild1", "nodes": [{ "text": "hello", "nodes": [] }] }, { "text": "hello", "nodes": [] } ] }] }, { "text": "parent2", "nodes": [{ "text": "child2", "nodes": [{ "text": "grandchild2", "nodes": [{ "text": "grandgrandchild1", "nodes": [{ "text": "hello", "nodes": [] }] }] }] }] } ]; var helloPaths = []; var valueToSearch = "hello"; function traverseAndCreatePath( obj, parent, valueToSearch ) { if ( Array.isArray( obj ) ) { obj.forEach( function(item){ traverseAndCreatePath( item, parent, valueToSearch ); }); } else { if ( parent ) { obj.path = parent.path.slice(); obj.path.push( obj.text ); } else { obj.path = [ obj.text ]; } if ( obj.text == valueToSearch ) { helloPaths.push( obj.path.slice() ); } if ( obj.nodes && obj.nodes.length ) { obj.nodes.forEach( function(item){ traverseAndCreatePath( item, obj, valueToSearch ); }); } } return obj; } traverseAndCreatePath( obj, null, valueToSearch ); console.log( helloPaths ); 

This is a Depth First Traversal 这是深度优先遍历

 var counter = 0; var finalArray = [] function test(arr, node) { arr.push(node.text); if (node.hasOwnProperty("nodes") && Array.isArray(node.nodes) && node.nodes.length != 0) { node.nodes.forEach(function(nodeChild) { test(arr, nodeChild); }) } else { finalArray[counter] = arr.slice(); counter++; } arr = arr.slice(0, -1); } var b =[ { "text" : "parent1", "nodes" :[ { "text": "child1", "nodes": [ { "text": "grandchild1", "nodes":[ { "text": "hello", "nodes": [] } ] }, { "text": "hello", "nodes":[] } ] } ] }, { "text" : "parent2", "nodes" :[ { "text": "child2", "nodes": [ { "text": "grandchild2", "nodes": [ { "text": "grandgrandchild1", "nodes": [ { "text": "hello", "nodes": [] } ] } ] } ] } ] } ] b.forEach(function(nodeVal) { test([], nodeVal) }) console.log(finalArray); 

Your function should recieve: 您的职能应获得:

  1. A list of nodes of any length 任意长度的节点列表

And return: 并返回:

  1. A list of paths of any length 任意长度的路径列表

For the base of this behavior, we'll use reduce . 作为此行为的基础,我们将使用reduce It loops over the list once, and can keep adding to the result when needed. 它循环遍历列表一次,并可以在需要时继续添加到结果中。

const helloPathsFromNodes = (nodes = [], paths = []) =>
  nodes.reduce(
    /* TODO */ ,
    paths
  )

For each node, you check whether it's the end of an individual path to determine if you need to recurse. 对于每个节点,请检查是否是单个路径的末尾,以确定是否需要递归。 To keep track of the current path, we'll need to pass along an additional parameter ( path ) and add to it along the way: 为了跟踪当前路径,我们需要传递一个附加参数( path )并沿其添加:

if (node.text === "hello") return [...path, "hello"]
else return goDeeper([...path, node.text])

Putting this together, you get: 放在一起,您将获得:

 const helloPathsFromNodes = (nodes = [], paths = [], path = []) => nodes.reduce( (acc, { text, nodes }) => text === "hello" ? [...acc, [...path, text]] : helloPathsFromNodes(nodes, acc, [...path, text]), paths ); console.log(helloPathsFromNodes(getData())); // Example Data function getData() { return [ { "text" : "parent1", "nodes" :[ { "text": "child1", "nodes": [ { "text": "grandchild1", "nodes":[ { "text": "hello", "nodes": [] } ] }, { "text": "hello", "nodes":[] } ] } ] }, { "text" : "parent2", "nodes" :[ { "text": "child2", "nodes": [ { "text": "grandchild2", "nodes": [ { "text": "grandgrandchild1", "nodes": [ { "text": "hello", "nodes": [] } ] } ] } ] } ] } ] }; 

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

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