我正试图用JavaScript从一个平面数组生成一个树结构。这通常是一个相当简单的命题-只需保留一个"堆栈"数组,其中引用了按嵌套深度排序的当前工作范围的祖先对象-在进入另一个嵌套级别时将一个新元素推到堆栈上,在离开一个嵌套级时将其弹出,用(新的(最后一个数组项引用的对象替换当前工作元素。
不幸的是,这需要通过引用传递的能力,而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,为了练习的目的,可以完全格式化不同地
如有任何意见,我们将不胜感激!
您的字符串看起来很容易解析。我想我会这样做:
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
这是一个你可能没有预料到的答案。
看看您的预期输出,我想知道生成JSON并在完成后对其进行评估是否最简单。根本没有参考资料。
当浏览你的平面阵列时,你基本上有三个操作:
- 将更多数据添加到当前对象
- 关闭当前对象
- 创建新的子对象
只需将适当的文本附加到您正在构建的JSON字符串上,就可以非常容易地完成这三项工作,因为您在迭代源数组时只需生成您在预期输出中显示的文本。完成后,通过eval运行该JSON字符串。如果输入中存在错误,您可能需要进行一些安全检查来验证每个数组和对象是否正确关闭,但它应该可以正常工作。
想法#2
您仍然可以使用堆栈数组。我不知道为什么你需要通过引用传递,但你可以把一个索引传递到数组中,让每个人都通过索引修改数组的主副本。使用本地函数,主数组可以是一个公共数据值,它是主函数的本地值,但本质上是所有子函数的全局值,因此它们可以共享对它的访问。
这看起来像这样:
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
}
想法#3
如果您想将数组传递到一个函数中并修改主副本(也许是您考虑通过引用传递的原因(,javascript设计模式是将数组传递进来并返回一个修改后的数组,用返回的修改过的数组替换整个原始数组。