I have a string parsed from a uint8array. something like
"[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]"
or
"[[],[[Class1(a1)],[Color(a1,200)]],[[IsLight(a1,0)]]]"
This is a 2D array with three fixed second level arrays => [ [], [], [] ]
, but the elements inside these three arrays are denoted using square brackets as well, which makes it very hard to find a pattern to use str.slice
. JSON.parse
doesn't work either.
Is there a way to actually convert this string to an array in Javascript?
I have a string parsed from a uint8array. something like
"[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]"
or
"[[],[[Class1(a1)],[Color(a1,200)]],[[IsLight(a1,0)]]]"
This is a 2D array with three fixed second level arrays => [ [], [], [] ]
, but the elements inside these three arrays are denoted using square brackets as well, which makes it very hard to find a pattern to use str.slice
. JSON.parse
doesn't work either.
Is there a way to actually convert this string to an array in Javascript?
Share Improve this question asked Jul 23, 2020 at 6:59 Jack HuJack Hu 431 silver badge6 bronze badges 4- 6 You might need to write a parser for this. There isn't a generic way to do it and using regexes is going to be hacky and hard to maintain. – VLAZ Commented Jul 23, 2020 at 7:02
-
1
Class1(a1)
is a function or just a string? – Flash Thunder Commented Jul 23, 2020 at 7:06 - The string is already valid JavaScript, so you can just use an existing JS parser (e.g. Babel) to parse it. – user1726343 Commented Jul 23, 2020 at 7:28
- just a string, I need the elements as strings in the array. – Jack Hu Commented Jul 23, 2020 at 9:42
4 Answers
Reset to default 3It seems like you can write a pretty straightforward parser:
const parse = (str) => {
let depth = 0;
let item = '';
let items = [];
for (let i = 0; i < str.length; i++) {
if (str[i] === '[') {
depth++;
if (depth === 2) {
items.push([]);
}
}
else if (str[i] === ']') {
if (depth === 3) {
items[items.length - 1].push(item);
item = '';
}
depth--;
}
else if (depth === 3) {
item += str[i]
}
}
return items;
}
console.log(parse("[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]"));
console.log(parse("[[],[[Class1(a1)],[Color(a1,200)]],[[IsLight(a1,0)]]]"))
function parse(s) {
return JSON.parse(s
.replace(/(?<=\[)([^\[\]])/g, "\"$1")
.replace(/([^\[\]])(?=\])/g, "$1\""));
}
const s1 = "[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]";
console.log(parse(s1));
const s2 = "[[],[[Class1(a1)],[Color(a1,200)]],[[IsLight(a1,0)]]]";
console.log(parse(s2));
Here is how the regexes work:
- A quotation mark is put before every character that is not a bracket, but follows an opening bracket (checked using positive lookbehind).
- A quotation mark is put after every character that is not a bracket, but precedes a closing bracket (checked using positive lookahead).
This way everything inside brackets is wrapped into strings and the bracket structure can be parsed into an Array
hierarchy using JSON.parse
.
IMPORTANT: If you'd also want to run the functions in the strings, and this code runs in the browser, do not use eval
! Use a Web Worker instead, which runs in a separate context (here is how).
UPDATE
The code can be simplified to use a single replace
:
function parse(s) {
return JSON.parse(s.replace(/(?<=\[)([^\[\]]+)(?=\])/g, "\"$1\""));
}
const s1 = "[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]";
console.log(parse(s1));
const s2 = "[[],[[Class1(a1)],[Color(a1,200)]],[[IsLight(a1,0)]]]";
console.log(parse(s2));
Although this version is simpler and faster, it's still much slower than @Dave's parser: https://jsperf./https-stackoverflow--questions-63048607
It can be achieved with the usage of negative look aheads and look behinds in regex
let a = "[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]"
a = a.replace(/(?<!])]/g, "\"")
a = a.replace(/\[(?!\[)/g, "\"")
console.log(JSON.parse(a))
Simple regex for that:
let x = "[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]";
x = x.replace(/([\w\)]){1}\]/g,'$1"').replace(/\[([\w]){1}/g,'"$1');
console.log(JSON.parse(x));
But if Class1()
, Price()
etc. are real functions, you can use for example eval()
(be extra cautious when using eval()
, may lead to code injections) for that:
let x = "[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]";
console.log(eval(x));
If u don't want additional []
around function results, you can merge the both:
let x = "[[[Class1(a1)],[Class2(a2)],[Price(a1,100)]],[[Class3(a3)],[Price(a3,200)]],[]]";
x = x.replace(/([\w\)]){1}\]/g,'$1').replace(/\[([\w]){1}/g,'$1');
console.log(eval(x));
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745625386a4636772.html
评论列表(0条)