【问题标题】:Recursively extract contents of (nested) parentheses in string递归提取字符串中(嵌套)括号的内容
【发布时间】:2017-03-21 13:04:03
【问题描述】:

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

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

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

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

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"));

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

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

已经为此苦苦挣扎了一段时间。有什么想法吗?


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

【问题讨论】:

  • 喜欢那些函数名
  • 您的代码无法生成该输出。您正在将单个字符推送到数组中。
  • @Oriol 好点,我忘了补充一点,我使用 RegEx 将字符串拆分为单词数组,没有字母符号。只要我再次使用笔记本电脑,就会更新。
  • @Oriol 或者我想既然您已经发布了解决方案,我将更新我的问题以反映字符串输入,以便您的答案可以成立。顺便说一句,谢谢您的回复。

标签: javascript arrays node.js recursion


【解决方案1】:

我通常会做如下的事情。

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

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

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

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%; }

【讨论】:

  • 这里有一个错误,这在上面的示例中留下了最后一个字母。点击“运行代码 sn-p”,它返回:"and", "manage" 没有 R。
【解决方案2】:

一种方法可能是将其重新格式化为 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"));

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

[[["a","b"],"ugh",["one","two"]],"pi"]

就目前而言,如果您的字符串在“)”和单词之间没有空格,或者两个“))”之间没有空格,但如果您的输入格式已知且严格为上面就可以了。否则,进一步的正则表达式调整或替换可以解决这个问题。

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

【讨论】:

    【解决方案3】:

    由于 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"));
    div.as-console-wrapper { max-height: 100%; }

    【讨论】:

      【解决方案4】:

      我必须为需要处理的公式执行此操作。这是我对“海滩之子”答案的即兴演奏:

      function formulaToArray(formula='') {
        const step1 = formula
          .split(/([\(\)\+\-\*\/])/)
          .map(x => x.trim())
          .join(' ')
          .replace(/\)\s\)/g, '))')
          .replace(/\(/g, '[')
          .replace(/\)\s/g, '], ')
          .replace(/\)/g, ']');
      
        const step2 = '[' + step1 + ']';
      
        const step3 = step2
          .replace(/[^\[\]\,\s]+/g, '"$&"')
          .replace(/" /g, '", ')
          .replace(/\,[\s]+\]/g, ']');
      
        return JSON.parse(step3);
      }
      
      console.log(formulaToArray('((developer or engineer )or (nurse or doctor)) and manager'));
      // [
      //   [
      //     ['developer', 'or', 'engineer'], 
      //     'or', 
      //     ['nurse', 'or', 'doctor']
      //   ], 
      //   'and', 
      //   'manager'
      // ]

      这解决了他引用的问题:')word' 和 ') )',虽然我猜不是 ') ) )'

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-23
        • 2021-09-02
        • 1970-01-01
        • 2021-07-27
        • 2019-10-04
        • 2016-12-24
        • 2011-01-07
        相关资源
        最近更新 更多