dylan dylan - 1 month ago 8
Node.js Question

Recursively extract contents of (nested) parentheses in string

I'm trying to write a function that extracts the words contained in parentheses into their own array, recursively to account for nested parentheses.

So for "((a b) ugh (one two)) pi", i'd like that to translate to the following structure:

[
[
[
"a",
"b"
],
"ugh",
[
"1",
"2"
],
]
"pi"
]


To that end, I've written the following function:

function shitshow(hell) {
var ssparts = [];
var done = false;
for (i in hell) {
let part = hell[i];
switch(part) {
case "(":
ssparts.push(shitshow(hell.slice(i+1)));
break;
case ")":
done = true;
break;
default:
ssparts.push(part);
}
if (done) break;
}
return ssparts;
}

console.log(shitshow("((developer or engineer) or (nurse or doctor)) and manager"));


It doesn't work. The array it returns for me (I'm testing this on Node 4):

[
"",
[
"doctor"
],
[],
"developer",
"or",
"engineer"
]


Been wrestling with this for a while. Any ideas?

Answer

I usually do something like the following.

An outer function receives the string as argument and declares outer variables used to iterate it.

The work is done in a recursive inner function which iterates until ).

This way all new strings I create are included in the returned array. No useless work is done.

function shitshow(str) {
  var i = 0;
  function main() {
    var arr = [];
    var startIndex = i;
    function addWord() {
      if (i-1 > startIndex) {
        arr.push(str.slice(startIndex, i-1));
      }
    }
    while (i < str.length) {
      switch(str[i++]) {
        case " ":
          addWord();
          startIndex = i;
          continue;
        case "(":
          arr.push(main());
          startIndex = i;
          continue;
        case ")":
          addWord();
          return arr;
      }
    }
    addWord();
    return arr;
  }
  return main();
}
console.log(shitshow("((developer or engineer ) or (nurse or doctor)) and manager"));
div.as-console-wrapper { max-height: 100%; }