字符串到多维数组



我有一个字符串示例

"abc|pqr[abc,xyz[abc,def]]"

现在我想输出到阵列

{
   abc : true,
   pqr : ['abc', xyz : [abc, def]]
}

我写的代码是这个,但它给了我"message": "Maximum call stack size exceeded"

var x = 'p[a,b,c,d]|q[small,large]|r[small,large]|s|t[w[x,y],z[a,b,c]]';
y = x.split("|");
function foo(query) {
        if (typeof query == "string") query = [query]
        var i = {}
        _(query).forEach(function(v) {
            regexQuery = v.match(/[(.*)]/);
            if (regexQuery != null) {
                index = regexQuery['index']
                if (regexQuery[1].match(/[(.*)]/) != null) {
                    i[regexQuery['input'].substr(0, index)] = foo(regexQuery[0])
                } else {
                    i[regexQuery['input'].substr(0, index)] = regexQuery[1].split(",");
                }
            } else {
                i[v] = true;
            }
        })
        return i;
    }
console.log(foo(y));

我知道regex不适用于此,但还有其他解决方案吗?

您可以使用下面的函数。对于问题中给出的输入:

p[a,b,c,d]|q[small,large]|r[small,large]|s|t[w[x,y],z[a,b,c]]

它产生这个对象:

{
  "p": [
    "a",
    "b",
    "c",
    "d"
  ],
  "q": [
    "small",
    "large"
  ],
  "r": [
    "small",
    "large"
  ],
  "s": true,
  "t": {
    "w": [
      "x",
      "y"
    ],
    "z": [
      "a",
      "b",
      "c"
    ]
  }
}

function toObject(x) {
    // Turn custom format into JSON text format, and then parse it.
    // In that object, find nested objects that could be turned into array.
    return (function flagsToArray(obj) {
        // Collect keys with nested objects.
        var nested = Object.keys(obj).filter(key => obj[key] !== true);
        // For those, call this function recursively
        nested.forEach(key => obj[key] = flagsToArray(obj[key]));
        // If no nesting, then turn this into an array
        return nested.length ? obj : Object.keys(obj);
    })(JSON.parse('{' + 
        x.replace(/|/g, ',') // treat '|' as ','
         .replace(/"/g, '"') // escape any double quotes
         .replace(/([^,|[]]+)/g, '"$1"') // wrap terms in double quotes
         .replace(/"[/g, '":[') // insert colon for assignment of arrays
         .replace(/"([,]])/g, '":true$1') // insert `true` assignment for atomic term
         .replace(/[/g, "{").replace(/]/g, "}") // replace array notation with object notation
        + '}'));
}
// Sample input
var x = 'p[a,b,c,d]|q[small,large]|r[small,large]|s|t[w[x,y],z[a,b,c]]';
// Convert
var obj = toObject(x);
// Output
console.log(obj);

该函数进行了多次替换,将自定义格式转换为JSON文本格式,将所有内容转换为嵌套对象(无数组)。然后在第二个过程中,即递归过程中,识别出没有嵌套对象的对象,即它们只由值为true的成员组成。然后,这些对象将被它们的数组"等价"替换,即具有对象键的数组。

您的查询字符串本质上是树的平面表示,其节点由以下项定义:

  • 要么一个名字
  • 或子节点的名称和列表

注意,我看不出,|之间有任何明显的区别,所以我假设它们实际上有相同的含义。

仅使用数组无法轻松存储此结构,而且混合使用数组和对象也会变得不必要的复杂。

因此,我建议只使用具有以下约定的对象:

  • key=节点名称
  • value=true1或子对象

1这是一个占位符。您也可以考虑使用一个空对象

有了这些假设,您的示例字符串"abc|pqr[abc,xyz[abc,def]]"将被解码为:

tree = {
  "abc": true,
  "pqr": {
    "abc": true,
    "xyz": {
      "abc": true,
      "def": true
    }
  }
}

这样的结构很容易操作。

例如,如果您想获得root > pqr > xyz的子节点,可以执行以下操作:

Object.keys(tree.pqr.xyz)

将返回:

["abc", "def"]

实施

以下是一个可能的实现:

function parse(query) {
  var n, tree = {}, node = tree, stk = [],
      sym = '', sz = (query += ',').length;
  for(n = 0; n < sz; n++) {
    switch(query[n]) {
      case '|':
      case ',':
        sym && (node[sym] = true);
        break;
      case '[':
        stk.push(node);
        node = node[sym] = {};
        break;
      case ']':
        sym && (node[sym] = true);
        node = stk.pop();
        break;
      default:
        sym += query[n];
        continue;
    }
    sym = '';
  }
  return tree;
}
console.log(parse("abc|pqr[abc,xyz[abc,def]]"));

相关内容

  • 没有找到相关文章

最新更新