将分隔文本转换为嵌套javascript对象/JSON

将分隔文本转换为嵌套javascript对象/JSON,javascript,json,string,d3.js,lodash,Javascript,Json,String,D3.js,Lodash,我有文本的格式 var text = "{{A-B-C}{A-C-B}D-B}{E}F" //example 1 文本可以是以下内容: var text = "{{{A-B-C}{C-A-B}D-E}{B-C}E-A}{F}G" //example 2 因此,节点结构可以更改,但-和{}的定界保持不变,以表示继承权 我想在此基础上创建一个树,作为javascript对象或JSON for d3js树布局。我可以使用lodash/jquery或任何其他我想要的库 对于上面的var文本示例1,我

我有文本的格式

var text = "{{A-B-C}{A-C-B}D-B}{E}F" //example 1
文本可以是以下内容:

var text = "{{{A-B-C}{C-A-B}D-E}{B-C}E-A}{F}G" //example 2
因此,节点结构可以更改,但-和{}的定界保持不变,以表示继承权

我想在此基础上创建一个树,作为javascript对象或JSON for d3js树布局。我可以使用lodash/jquery或任何其他我想要的库

对于上面的var文本示例1,我需要的最终布局如下图所示

如何将字符串转换为以下格式的嵌套数据(对于
var text
example 1)。我一直在努力寻找一种方法来做到这一点。任何帮助或指导都将不胜感激

var textobject = {
  name: "F",
  children: [{
      name: "E",
      children: []
    },
    {
      name: "B",
      children: [{
        name: "D",
        children: [{
          name: "B",
          children: [{
            name: "C",
            children: [{
              name: "A",
              children: []
            }, ]
          }, ]
        }, {
          name: "C",
          children: [{
            name: "B",
            children: [{
              name: "A",
              children: []
            }, ]
          }, ]
        }, ]
      }, ]
    },
  ]
}

可以通过使用数组作为堆栈来解决此问题。下面代码的注释中有一个适当的解释

function parseTree(string) {
  // split string into an array
  // reduce the array into a proper tree where the 
  // first and last item will be the entire tree, hence,
  // the access of the first index from the last part
  // of this expression
  return string.split(/(}|{|\-)/)
    .reduce(parseTreeReducer, [])[0];
}

function parseTreeReducer(array, ch, index, original) {
  // always track the index of the open bracket 
  // from the array stack
  let indexBracket = array.lastIndexOf('{');

  if(ch === '{') { // is it an open bracket?
    // store it in the array stack!
    array.push(ch); 
  } else if(ch === '}') { // is it a close bracket?
    // remove the last open bracket
    // this prepares the nodes after the open bracket index
    // to be the children of the next node
    array.splice(indexBracket, 1); 
  } else if(ch !== '-' && ch) { // make sure to ignore '-' key

    // push the node in the array stack
    array.push({ 
      name: ch, // name
      // ensure that we only get the nodes that are after the 
      // last open bracket from the array stack and remove them.
      // These removed nodes will be assigned as children for
      // this current node
      children: array.splice(
        // make sure we don't delete the open bracket
        indexBracket + 1, 
        // only remove items beyond the open bracket index
        array.length - indexBracket - 1 
      ).reverse() // reverse to represent the expected output (optional!)
    });

  }
  // return the array stack
  return array;
}
函数解析树(字符串){
//将字符串拆分为数组
//将数组缩减为适当的树,其中
//第一项和最后一项将是整个树,因此,
//从最后一部分访问第一个索引
//这句话的意思
返回字符串.split(/(}{124; \-)/)
.reduce(parsetreducer,[])[0];
}
函数解析器还原程序(数组、通道、索引、原始){
//始终跟踪开放式支架的索引
//从数组堆栈
设indexBracket=array.lastIndexOf('{');
如果(ch=='{'){//它是一个开括号吗?
//将其存储在数组堆栈中!
阵列推送(ch);
}else if(ch=='}'){//是否为右括号?
//拆下最后一个打开的支架
//这将在开括号索引之后准备节点
//成为下一个节点的子节点
阵列拼接(独立支架,1);
}否则,如果(ch!='-'&&ch){//请确保忽略'-'键
//在数组堆栈中推送节点
array.push({
name:ch,//name
//确保只获取位于
//将最后一个打开的支架从阵列堆栈中取出。
//这些删除的节点将被指定为的子节点
//此节点为当前节点
子项:array.splice(
//确保我们没有删除开放式括号
indexBracket+1,
//仅删除左括号索引以外的项目
array.length-indexBracket-1
).reverse()//表示预期输出的reverse(可选!)
});
}
//返回数组堆栈
返回数组;
}
/*下面的代码仅供演示使用*/
var input=document.querySelector('input');
var输出=document.querySelector('pre');
setOutput();
input.addEventListener('keyup',setOutput);
函数setOutput(){
output.innerHTML=JSON.stringify(parseTree(input.value),0,4);
}
.as控制台包装{最小高度:100%;顶部:0}
输入{宽度:100%}
前{背景色:#ccc;填充:1em}



一直在努力寻找一种有效的方法。
从你认为效率低下的工作开始,然后改进它-发布代码?很抱歉,某些性能,让我重新表述一下,我还没有取得成功的结果。在图像和文本输入中:
a-B-C
位于同一个l上evel,但在所需的输出中:
A
B
的子级,这是
C
的子级,有点困惑..感谢您查看@Taki。所有内容都是某事物的子级。即-表示左字符是右字符的子级。{}括号表示有分支的孩子。这说明了一点吗?-请原谅我手机上的简短。非常令人印象深刻。谢谢。但是,如果名称有多个字符,则不能使用此选项。例如,对于像
“{Axx xBx xCx}{xAxx Cxx Cxx Bxx}xxx Bxx}{xEx}xFx”这样的字符串,现在的名称类似于
“name”:“xFx”
或者您可以修改代码以放入名称中,直到到达下一个分隔符“{”“}”或“-”为止吗?@Coola检查我的更改。这很好,但我最终使用.split和regex来拆分字符串,如:
var strarr=string.split(/(}{124;}{124\-)/).filter(函数(n){return n!==“”);
然后将此数组传递给
.reduce(parsetreducer,[])[0]
。与您的方法相比,您认为这会提供更好/更差的性能吗?因为我的方法调用
parsetreducer
函数的正确次数会更少?好吧,分割应该很好,但是可以删除
数组#过滤器
,我们可以在
if else
链的最后一部分添加一个简单的检查
Array#reduce
回调。