最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

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

matteradmin3PV0评论

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));
Post a comment

comment list (0)

  1. No comments so far