Javascript 从解析的textinput创建嵌套json

Javascript 从解析的textinput创建嵌套json,javascript,json,reactjs,parsing,recursion,Javascript,Json,Reactjs,Parsing,Recursion,我正试图创建一个javascript函数来将文本解析为嵌套的JSON,但我一直无法递归地管理它 因此,基本上转换文本框中的内容: todo list learn js hello world shopping list costco procrastination list 为此: [ {'val':'todo list','children':[{'val':'learn js','children':['val':'hello world']}]}, {'val':'sh

我正试图创建一个javascript函数来将文本解析为嵌套的JSON,但我一直无法递归地管理它

因此,基本上转换文本框中的内容:

todo list
  learn js
     hello world
shopping list
  costco
procrastination list
为此:

[
{'val':'todo list','children':[{'val':'learn js','children':['val':'hello world']}]},
{'val':'shopping list','children':[{'val':'costco'}]},
{'val':'procrastination list'}
]
我想到了这个:

const TxtParser = txtBoxVal => {
  let txtArr = [];
  let nbrSpacesPrev = 0;
  if (txtBoxVal) {
    if (txtBoxVal.split("\n").length) {
      let lines = txtBoxVal.split("\n");
      let numNewLines = txtBoxVal.split("\n").length;
      let i;
      for (i = 0; i < numNewLines; i++) {
        if (lines[i].search(/\S/) !== -1) {
          let txtObj = {};
          txtObj["line"] = lines[i].trim();
          // check for space diff
          txtObj["nbrSpaces"] = lines[i].search(/\S/);
          txtArr.push(txtObj);
        }
      }
    }
  }
  return txtArr;
}; 
const TxtParser=txtBoxVal=>{
设txtArr=[];
设nbrSpacesPrev=0;
if(txtBoxVal){
if(txtBoxVal.split(“\n”).length){
让lines=txtBoxVal.split(“\n”);
设numNewLines=txtBoxVal.split(“\n”).length;
让我;
对于(i=0;i
我只得到线性结果:


我不知道如何创建嵌套子对象。

这是一个部分答案,但它可能会帮助您构建对象:

var text = `todo list
  learn js
    hello world
  other level
   deeper
shopping list
  costco
procrastination list`;

var paths = []; // this will store our path tree

parseText = () => {
    var lines = text.split("\n");
    var outputObject = {};

    var pathsStack = [];
    var previousSpaces = 0;

    lines.forEach( line => {
      //var line = lines[key];
      var spaces = line.match(/^\s*/)[0].length; // search 

      if (spaces === 0){ // reset path stack
        pathsStack = [line.trim()];
      } else if (spaces > previousSpaces) {
        pathsStack.push(line.trim());
      } else if (spaces === previousSpaces) {
        pathsStack.pop(); // remove last item
        pathsStack.push(line.trim());
      } else if (spaces < previousSpaces) {
        pathsStack.pop(); // remove last two items
        pathsStack.pop(); 
        pathsStack.push(line.trim());
      } 

      previousSpaces = spaces;

      paths.push(pathsStack.join("."));
    });
    console.log(paths);
    /* 
    this will output an array in the following form:
      0: "todo list"
      1: "todo list.learn js"
      2: "todo list.learn js.hello world"
      3: "todo list.other level"
      4: "todo list.other level.deeper"
      5: "shopping list"
      6: "shopping list.costco"
      7: "procrastination list"

    you can now iterate through this array and insert it into your target object.
    */
  }
var text=`todo列表
学习js
你好,世界
其他级别
更深的
购物清单
好市多
拖延清单`;
变量路径=[];//这将存储我们的路径树
parseText=()=>{
变量行=text.split(“\n”);
var outputObject={};
var pathsStack=[];
var-previousSpaces=0;
lines.forEach(line=>{
//变量行=行[键];
var spaces=line.match(//^\s*/)[0].length;//搜索
如果(空格===0){//重置路径堆栈
pathsStack=[line.trim()];
}else if(空格>上一个空格){
pathsStack.push(line.trim());
}else if(空格===previousSpaces){
pathsStack.pop();//删除最后一项
pathsStack.push(line.trim());
}else if(空格<以前的空格){
pathsStack.pop();//删除最后两项
pathsStack.pop();
pathsStack.push(line.trim());
} 
previousSpaces=空格;
paths.push(pathsStack.join(“.”);
});
console.log(路径);
/* 
这将以以下形式输出数组:
0:“待办事项列表”
1:“待办事项列表.学习js”
2:“todo list.learn js.hello world”
3:“待办事项列表。其他级别”
4:“待办事项列表。其他级别。更深”
5.“购物清单”
6:“购物清单.好市多”
7.“拖延清单”
现在,您可以遍历该数组并将其插入到目标对象中。
*/
}

这是部分答案,但可能有助于构建对象:

var text = `todo list
  learn js
    hello world
  other level
   deeper
shopping list
  costco
procrastination list`;

var paths = []; // this will store our path tree

parseText = () => {
    var lines = text.split("\n");
    var outputObject = {};

    var pathsStack = [];
    var previousSpaces = 0;

    lines.forEach( line => {
      //var line = lines[key];
      var spaces = line.match(/^\s*/)[0].length; // search 

      if (spaces === 0){ // reset path stack
        pathsStack = [line.trim()];
      } else if (spaces > previousSpaces) {
        pathsStack.push(line.trim());
      } else if (spaces === previousSpaces) {
        pathsStack.pop(); // remove last item
        pathsStack.push(line.trim());
      } else if (spaces < previousSpaces) {
        pathsStack.pop(); // remove last two items
        pathsStack.pop(); 
        pathsStack.push(line.trim());
      } 

      previousSpaces = spaces;

      paths.push(pathsStack.join("."));
    });
    console.log(paths);
    /* 
    this will output an array in the following form:
      0: "todo list"
      1: "todo list.learn js"
      2: "todo list.learn js.hello world"
      3: "todo list.other level"
      4: "todo list.other level.deeper"
      5: "shopping list"
      6: "shopping list.costco"
      7: "procrastination list"

    you can now iterate through this array and insert it into your target object.
    */
  }
var text=`todo列表
学习js
你好,世界
其他级别
更深的
购物清单
好市多
拖延清单`;
变量路径=[];//这将存储我们的路径树
parseText=()=>{
变量行=text.split(“\n”);
var outputObject={};
var pathsStack=[];
var-previousSpaces=0;
lines.forEach(line=>{
//变量行=行[键];
var spaces=line.match(//^\s*/)[0].length;//搜索
如果(空格===0){//重置路径堆栈
pathsStack=[line.trim()];
}else if(空格>上一个空格){
pathsStack.push(line.trim());
}else if(空格===previousSpaces){
pathsStack.pop();//删除最后一项
pathsStack.push(line.trim());
}else if(空格<以前的空格){
pathsStack.pop();//删除最后两项
pathsStack.pop();
pathsStack.push(line.trim());
} 
previousSpaces=空格;
paths.push(pathsStack.join(“.”);
});
console.log(路径);
/* 
这将以以下形式输出数组:
0:“待办事项列表”
1:“待办事项列表.学习js”
2:“todo list.learn js.hello world”
3:“待办事项列表。其他级别”
4:“待办事项列表。其他级别。更深”
5.“购物清单”
6:“购物清单.好市多”
7.“拖延清单”
现在,您可以遍历该数组并将其插入到目标对象中。
*/
}
编辑:添加了
.filter
行以清理输入,并切换到Thankyou的输入数据进行演示。)


这里有一种方法。我们将转换为如下所示的中间格式:

[
{缩进:0,val:“待办事项列表”},
{缩进:2,val:“学习js”},
{缩进:5,val:“你好,世界”},
{缩进:0,val:“购物清单”},
{缩进:2,val:“好市多”},
{缩进:0,val:“拖延列表”}
]
其中,
缩进
s计算每行文本前的空格。然后,通过保留最近节点的父节点堆栈,搜索缩进值低于当前节点的第一个节点,并将当前节点添加为其子节点之一,我们将该列表折叠成如下数据结构:

{
缩进:-1,
儿童:[
{
缩进:0,
瓦尔:“待办事项列表”,
儿童:[
{indent:2,val:“学习js”,子项:[{indent:5,val:“hello world”}]
],
},
{缩进:0,val:“购物清单”子项:[{缩进:2,val:“好市多”]},
{缩进:0,val:“拖延列表”}
],
}
最后,我们递归该结构的子结构,删除所有嵌套的
indent
属性,我们得到您的输出

此代码基于此理念:

//Helper函数
const deepMap=(fn)=>({children,…rest})=>({
…fn({…rest}),
…(儿童?{children:children.map(deepMap(fn))}:{})
})
//主要功能
常量提取树=(文本)=>
文本
.split(“\n”)
.filter((行)=>/\S/.test(行))
.map(s=>s.match(/^(\s*)(.*)$/).slice(1))
.map(([prefix,val])=>({indent:prefix.length,val}))
.reduce((路径、节点)=>{
常量{indent,val}=node
const parentIdx=path.findIndex(node=>node.indent