遍历JSON数据中的嵌套数组

时间:2018-02-07 08:55:18

标签: javascript arrays json recursion nested

我有这样的数据:

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

                }
            ]
        }
    }

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

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

我想要这个“路径”数组。请注意,如果元素的文本值是“hello”,则此元素的“节点”长度为0.我认为我在递归时出错了。

3 个答案:

答案 0 :(得分:0)

你需要

  • 使用递归遍历对象
  • 沿途分配路径
  • 并最终在当前文本与文字匹配时保持记录这些路径

<强>演示

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

答案 1 :(得分:0)

这是深度优先遍历

&#13;
&#13;
$filename = "input.txt";
$in = fopen($filename,'r+');
if($in)
{
  $count = 0;
  $last = 0;

  // loop every line
  while (($lines = fgets($in)) !== false)
  {
    $count++;
    if( $count % 10 == 0 && preg_match('/;/',$lines) )
    {
      $content = file_get_contents($filename, FALSE, null, ftell($in));

      $insertLine = preg_replace('/;/',"; commit;", $lines);

      // go back to the end of the last line
      fseek($in, $last, SEEK_SET);
      fwrite($in, $insertLine);

      // insert the content from the next line to the end, otherwise it will modified. You see this if you remove this line 
      fwrite($in, $content);
    }
    else
    {
      //Save the position where ends the last line
      $last = ftell($in);
    }
  }
}
else
{
  echo "Input file cannot be opened\n";
}

fclose($in);
&#13;
&#13;
&#13;

答案 2 :(得分:0)

你的功能应该收到:

  1. 任意长度的节点列表
  2. 返回:

    1. 任意长度的路径列表
    2. 对于此行为的基础,我们将使用reduce。它循环遍历列表一次,并且可以在需要时继续添加结果。

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

      对于每个节点,检查是否是个人路径的末尾,以确定是否需要递归。为了跟踪当前路径,我们需要传递一个额外的参数(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": [] } ] } ] } ] } ] } ]  };