我有一个字符串示例
"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]]"));