将分隔文本转换为嵌套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
回调。