convert string with square brackets to array or list in Javascript - Stack Overflow

I have a string parsed from a uint8array. something like"[[[Class1(a1)],[Class2(a2)],[Price(a1,10

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.parsedoesn'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.parsedoesn'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
Add a ment  | 

4 Answers 4

Reset to default 3

It 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:

  1. A quotation mark is put before every character that is not a bracket, but follows an opening bracket (checked using positive lookbehind).
  2. 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信