【问题标题】:How to avoid multiple if statements when checking a regexp match检查正则表达式匹配时如何避免多个 if 语句
【发布时间】:2012-09-22 12:42:38
【问题描述】:

目前我有这样的代码..

var result = line.match( some regexp );
  if (result !== null) {
      return callback({ a: 'aaaaa', b: bvariable });
    });
  }

var result = line.match( some other regexp );
  if (result !== null) {
      return callback({ d: 'ddddd', c: bvariable });
    });
  }

我有大约 10 个这些都具有不同的正则表达式和回调,并且列表会变得更大。有没有更好/更清洁的方法?

【问题讨论】:

  • 您需要展示更多 if 块的外观,以便我们知道该代码中有多少共性。
  • 我在大约 5 年后查看了这个问题,但仍然没有得到满意的答案,以避免通过代码进行多次存在性检查。
  • 如果我没记错的话,没有办法绕过多行 if 语句作为返回对象的内容,其中依赖于匹配的正则表达式。

标签: javascript node.js


【解决方案1】:

您可以将正则表达式和回调重构为“关联数组”(对象),然后概括其余部分:

var regexs = { 
    regex1: {
        regex: /./,
        callback: function () {
            // callback stuff here
        }
    },
    regex2: {
        regex: /[a-z]/,
        callback: function () {
            // callback stuff here
        }
    }
};

var result = line.match(regexs.regex1.regex);
if (result !== null) {
    return regexs.regex1.callback();
}

【讨论】:

    【解决方案2】:

    创建一个关联数组对。每对中的第一个元素是一个正则表达式,第二个是回调。遍历数组并匹配正则表达式,如果匹配则调用回调。

    var assoc = [
        { r: /\d+/, f: function (m) { console.log(m[1]); } },
        { r: /\w+/, f: function (m) { console.log(m[2] + m[3]); } }
    ];
    
    for (var i = 0; i < assoc.length; i++) {
        var m = line.match(assoc[i].r);
        if (m) {
            return assoc[i].f(m);
        }
    }
    

    【讨论】:

      【解决方案3】:

      你可以去掉结果变量

      if(line.match( some regexp )) {
        return callback({ a: 'aaaaa', b: bvariable });
      }
      
      if(line.match( some other regexp )) {
        return callback({ d: 'ddddd', c: bvariable });
      }
      

      由于 match 函数总是返回 null 或数组,可以安全地假设如果匹配失败,返回的 null 将被强制转换为 false,如果匹配成功则返回数组(无论它有多少元素)将被强制转换为 true。

      【讨论】:

        【解决方案4】:

        考虑:

        input = "foo bar baz"
        regexes = [
            /aa/,
            /ba./,
            /quux/,
        ]
        
        regexes.some(function(re) {
            if(re.test(input)) {
                // do stuff
                return true;
            }
            return false;
        })
        

        请注意,您不需要match,除非您实际使用它返回的内容。

        【讨论】:

          【解决方案5】:

          如果您的正则表达式模式是简单的字符串,并且假设您希望第一个模式在第二个之前匹配,您可以:

          var pattern1='aaa',
              pattern2='bbb',
              RE=new RegExp('('+pattern1+'|'+pattern2+')'); // matches pattern1 OR pattern2
          
          if(line.match(RE)){
              var result=RegExp.$1; // content of first pair of capturing parens
              if(result===pattern1) {
                  return callback(/* args specific to first pattern */);
              }
              else if(result===pattern2){
                  return callback(/* args specific to second pattern */);
              }
              else {
                  return callback(/* args for no match */);
              }
          }
          

          【讨论】:

          • 如果您有大量可能的匹配模式,您将希望通过按字母顺序排列模式并确保将多个匹配项(如 (aabb|aacc) 折叠到类似 (aa(?:bb|cc)) 的东西,但理论上一个正则表达式可以有大量的替代项。
          猜你喜欢
          • 1970-01-01
          • 2013-09-13
          • 2020-08-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-29
          • 2013-12-10
          相关资源
          最近更新 更多