递归提取字符串中(嵌套)括号的内容

dyl*_*lan 6 javascript arrays recursion node.js

我正在尝试编写一个函数,将括号中包含的单词提取到它们自己的数组中,递归地考虑嵌套括号。

因此,对于“((ab) ugh (one two)) pi”,我希望将其转换为以下结构:

[
  [
    [
      "a",
      "b"
    ],
    "ugh",
    [
      "1",
      "2"
    ],
  ]
  "pi"
]
Run Code Online (Sandbox Code Playgroud)

为此,我编写了以下函数:

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"));
Run Code Online (Sandbox Code Playgroud)

它不起作用。它为我返回的数组(我正在节点 4 上对此进行测试):

[
  "",
  [
    "doctor"
  ],
  [],
  "developer",
  "or",
  "engineer"
]
Run Code Online (Sandbox Code Playgroud)

一直在努力解决这个问题。有任何想法吗?


编辑:正如@Oriol 在这篇文章的评论中提到的,我发布的代码不会产生我发布的输出。这是因为我忘记提及/包括我将初始字符串转换为单词和非字母数字符号数组的地方。为此事道歉。因为@Oriol 已经发布了一个可行的解决方案,所以我将包含此通知而不是更新我的代码,以便他发布的解决方案可以站得住脚。

Ori*_*iol 8

我通常会做类似以下的事情。

外部函数接收字符串作为参数并声明用于迭代它的外部变量。

工作是在递归内部函数中完成的,该函数迭代直到)

这样我创建的所有新字符串都包含在返回的数组中。没有做无用的工作。

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"));
Run Code Online (Sandbox Code Playgroud)
div.as-console-wrapper { max-height: 100%; }
Run Code Online (Sandbox Code Playgroud)


Son*_*ach 7

一种方法可能是将其重新格式化为 JSON,然后让 JSON.parse() 完成所有工作。就像是:

function blah(string) {
	string = string.replace(/\(/g, "[");
	string = string.replace(/\)\s/g, "], ");
	string = string.replace(/\)/g, "]");
	string = string.replace(/\s+/, ", ");
	string = "[" + string + "]";
	string = string.replace(/[^\[\]\,\s]+/g, "\"$&\"");
	string = string.replace(/" /g, "\", ");

	return JSON.parse(string);
}

console.log(blah("((a b) ugh (one two)) pi"));
Run Code Online (Sandbox Code Playgroud)

编辑:修复了正则表达式的一些问题并作为运行代码发布。与测试字符串一起使用。

[[["a","b"],"ugh",["one","two"]],"pi"]
Run Code Online (Sandbox Code Playgroud)

就目前情况而言,如果您的字符串“)”和单词之间没有空格,或者两个“))”之间没有空格,则它将无法处理,但如果您的输入格式已知并且如上所述严格,那么它就可以了。否则,进一步的正则表达式调整或替换可以解决这个问题。

根据文本来源的位置,如果可以从来源获取 JSON 格式的文本,那么这将使其成为一个简单的单行解决方案。我之所以提到这一点,是因为您的字符串已经与 JSON 类似,但它们可能来自您对格式没有太多控制权的来源。


小智 5

由于 Ciantic 在 Oriol 的回答中发现的“管理”与“经理”错误,我一直在寻找更完整的解决方案。

function shitshow(str) {
  var i = 0;
  var trailingWhiteSpace = str[str.length - 1] === " ";
  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;
      }
    }
    if(!trailingWhiteSpace){
      i = i + 1;
      addWord();
    }
    return arr;
  }
  return main();
}
console.log(shitshow("((developer or engineer ) or (nurse or doctor)) and manager"));
Run Code Online (Sandbox Code Playgroud)
div.as-console-wrapper { max-height: 100%; }
Run Code Online (Sandbox Code Playgroud)