【问题标题】:Traverse in nested arrays in JSON data遍历 JSON 数据中的嵌套数组
【发布时间】:2018-07-17 11:47:11
【问题描述】:

我有这样的数据:

    {
        {
            "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": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]

                }
            ]
        }
    }

我想要的是创建一个路径数组,其中包含“文本”值为“hello”的元素的路径。比如根据这个数据:

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

我想要这个“路径”数组。请注意,如果元素的文本值为“hello”,那么该元素的“nodes”长度为0。我想我在递归中犯了一个错误。

【问题讨论】:

  • 我认为我在递归中犯了一个错误请分享你的尝试。

标签: javascript arrays json recursion nested


【解决方案1】:

你需要

  • 使用递归遍历对象,
  • 沿途分配路径
  • 最后在当前文本与文本匹配时记录那些路径

演示

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 );

【讨论】:

  • 我还有一个问题。根据这个解决方案,我应该怎么做才能创建没有路径文本值但有这个节点索引的数组?所以我想要的数组应该是这样的:[0,1,1,0,2],[0,1,0] ...
【解决方案2】:

这是深度优先遍历

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);

【讨论】:

    【解决方案3】:

    你的函数应该收到:

    1. 任意长度的节点列表

    然后返回:

    1. 任意长度的路径列表

    对于此行为的基础,我们将使用reduce。它在列表上循环一次,并且可以在需要时继续添加到结果中。

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

    对于每个节点,您检查它是否是 individual 路径的结尾以确定是否需要递归。为了跟踪当前路径,我们需要传递一个额外的参数 (path) 并一路添加:

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

    把这些放在一起,你会得到:

    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": [] } ] } ] } ] } ] } ]  };

    【讨论】:

    • 我还有一个问题。根据这个解决方案,我应该怎么做才能创建没有路径文本值但有这个节点索引的数组?所以我想要的数组应该是这样的:[0,1,1,0,2],[0,1,0] ...
    • 您向 reduce 方法添加第三个参数:(acc, { text, nodes }, i)。添加 i: [...path, i] 而不是向路径添加文本
    • 这正是我想要的。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    相关资源
    最近更新 更多