如何在JavaScript中将字符串树解析为数组

How to parse string tree into array in JavaScript

本文关键字:数组 字符串 JavaScript      更新时间:2023-09-26

假设我得到了一个API响应,它返回一个类似树的结构,如下所示:

"gw43g: (-95.147, 38.5818); " +
"jp987h: (" +
         "bvp7: (-97.450, 30.150); " +
         "7g8oi: (" +
                 "34ilht: (-82.192997, 29.39719); " +
                 "34hb1: (-122.25, 37.47)); " +
         "b238: (-71.0349, 42.2129)); " +
"ao8yh: (-90.147, 42.5818);"

这是一根绳子。

使用JavaScript,我需要将其转换为这样的数组。。

["(-95.147, 38.5818)",
  "(bvp7: (-97.450, 30.150); 7g8oi: (...)...)",
  "(-90.147, 42.5818)"]

使得每对括号的内部都是一个数组项,无论最外层的一对中包含多少嵌套的括号。

我运气不好,所以我请求你的人帮忙。这是我试过的。

function getCoords(str) {
    return str.split(';').map(function(s) {
        return s.substring(s.indexOf('(')+1, s.lastIndexOf(')'));
    });
}

但这大错特错。请随意调用任何功能性工具包(undercore.js等)。不,这不是家庭作业,这是我正在写的一本书。谢谢你的帮助!

您可以像这样使用Array.prototype.reduce():

var str = "gw43g: (-95.147, 38.5818); " +
"jp987h: (" +
  "bvp7: (-97.450, 30.150); " +
  "7g8oi: (" +
     "34ilht: (-82.192997, 29.39719); " +
     "34hb1: (-122.25, 37.47)); " +
  "b238: (-71.0349, 42.2129)); " +
"ao8yh: (-90.147, 42.5818);"
var cnt = 0; // keep count of opened brackets
var result = Array.prototype.reduce.call(str, function(prev, curr) {
  if (curr === '(' && cnt++ === 0) prev.push('');
  if (cnt > 0) prev[prev.length-1] += curr;
  if (curr === ')') cnt--;
  return prev;
}, []);
console.log(result);

JSFiddle镜像

您可能应该为此使用解析器,但这里有一个快速而肮脏的解决方案,有点像迷你解析器:

var src = "gw43g: (-95.147, 38.5818) .... ";
var re = /('w+:'s*'()|(');?)|((?:(?!'w+:'s*'(|');?).)+)/g;
var output = [];
var match;
var stackCount = 0;
while ((match = re.exec(src)))
{
    if (match[1]) {
        if (stackCount == 0) output.push('');
        stackCount++;
    }
    else if (match[2]) {
        stackCount--;
    }
    output[output.length-1] += match[0];
}
console.log(output);

jsFiddle

正则表达式将标记分为三类,一类是堆栈开启器,一类为堆栈关闭器,或是中性。如果它找到一个堆栈启动器,而堆栈上什么都没有,它会添加一个新的数组项,如果它找到了一个更接近的数组项则会将堆栈降低一。在堆栈为零之前,它将一直追加到当前数组项。

我忍不住了,所以我继续完成了简单的解析器,这样字符串就可以输出为一个树,其中根属性是键(gw43g),每个属性要么有一个X,Y值,要么是树上的一个分支。

function parseBody(str) { 
    // rey: http://rey.gimenez.biz/s/fxd02f
    var re = /'s+|('w+)'s*:'s*'(|(');?)|((['-+]?'s*(?:'d*'.'d*|'d+))'s*,'s*(['-+]?'s*(?:'d*'.'d*|'d+)))/g;
    var output = [];
    var match;
    var newObj;
    var root = { children: { } }
    var branch = root;
    while ((match = re.exec(str)))
    {
        // key and open
        if (match[1]) {
            newObj = { parent: branch, children: { } };
            branch.children[match[1]] = newObj;
            // new stack
            branch = newObj;
        }
        // 
        else if (match[2]) {
            // move up stack
            branch = branch.parent;
        }
        else if (match[3]) {
            branch.X = parseFloat(match[4]);
            branch.Y = parseFloat(match[5]);
        }
    }
    return root;
}

jsFiddle

正则表达式