我正在尝试使用平面数组在JavaScript中生成树结构。这通常是一个相当简单的命题 - 只需保留一个'stack'数组,引用当前工作范围的祖先对象,通过嵌套深度排序 - 在进入另一个嵌套级别时将新元素推入堆栈,并在离开时将其弹出一,用(新)最后一个数组项引用的对象替换当前工作元素。
不幸的是,这需要能够通过引用传递,这是JavaScript没有的(好吧,没有任何有意义的方式,我知道如何使用这个问题。)
为了给出一些背景知识,我试图转换包含嵌套XML样式的任意长/复杂的字符串(但不是 XML,因此不能使用XML解析器)令牌变成类似下面的结构:
预期输入:
[
"<token>",
"<my non compliant token>",
"some text at this level",
"<some other token>",
"some more text",
"<yet another token>",
"more text",
"</yet another token>",
"blah!",
"</some other token>",
"</token>",
"more text"
]
预期输出
[
{
"token": "<token>",
"children": [
{
"token": "<my non compliant token>",
"children": [
"some text at this level",
{
"token": "<some other token>",
"children": [
"some more text",
{
"token": "<yet another token>",
"children": [ "more text" ]
},
"blah!"
]
}
]
}
]
},
"more text"
]
澄清一下 - 我不是在完成整个算法之后(但是如果你想提供你的实现我会感兴趣) - 只是一个很好的方法来保持输出树中的当前位置(或者完全不同/更好的方式)生成树对象!)不要过于关注令牌如何工作 - 它们不是XML,并且为了练习的目的可以完全不同地格式化。
非常感谢任何输入!
答案 0 :(得分:2)
您的字符串看起来很容易解析。我想我会做这样的事情:
var stack = [];
var array = [];
for (var i in strings) {
var s = strings[i];
if (s.indexOf("</") == 0) {
array = stack.pop();
} else if (s.indexOf("<") == 0) {
var obj = {token: s, children: []};
array.push(obj);
stack.push(array);
array = obj.children;
} else {
array.push(s);
}
}
答案 1 :(得分:1)
这是你可能没想到的答案。
看看你期望的输出,我想知道是否最简单的方法就是生成JSON然后在你完成后再评估它。根本没有参考。
在浏览平面阵列时,您基本上有三个操作:
通过将正确的文本附加到正在构建的JSON字符串上,您可以非常轻松地完成所有这三个操作,因为您在遍历源数组时只是生成您在预期输出中显示的文本。完成后,通过eval运行该JSON字符串。如果输入中存在错误,您可能需要进行一些安全检查以验证每个阵列和对象是否正确关闭,但它应该可以正常工作。
您仍然可以使用堆栈数组。我不确定你为什么需要通过引用传递,但是你可以只将一个索引传递给数组,并让每个人通过索引修改数组的主副本。使用本地函数,主数组可以是主函数本地的公共数据值,但对于所有子函数而言基本上是全局的,因此它们可以共享对它的共享访问。
这看起来像这样:
function ParseRawData(rawData)
{
var parentScopeArray = []; // main parent scope of objects
function processTag(x)
{
// you can access parentScopeArray directly here and
// and be accessing it by reference
}
// other code or local functions here
}
如果你想将数组传递给一个函数并修改主副本(也许是你想通过引用传递的原因),javascript设计模式是传入数组并返回一个修改过的数组,取而代之整个原始数组,包含返回的修改后的数组。