用于JavaScript中字符串匹配的switch语句


193

我该如何为以下条件写一个swtich?

如果网址包含 “ foo”,则settings.base_url为“ bar”。

以下实现了所需的效果,但是我感觉这在切换中将更易于管理:

var doc_location = document.location.href;
var url_strip = new RegExp("http:\/\/.*\/");
var base_url = url_strip.exec(doc_location)
var base_url_string = base_url[0];

//BASE URL CASES

// LOCAL
if (base_url_string.indexOf('xxx.local') > -1) {
    settings = {
        "base_url" : "http://xxx.local/"
    };
}

// DEV
if (base_url_string.indexOf('xxx.dev.yyy.com') > -1) {
    settings = {
        "base_url" : "http://xxx.dev.yyy.com/xxx/"
    };
}

Answers:


352

你不能做到这一点的switch,除非你正在做的字符串匹配; 在做子串匹配。 (这不是正确,因为肖恩在评论中指出。见注底。)

如果您对顶部的正则表达式感到满意,那么可以删除不需要在匹配中进行比较的所有内容,则不需要子字符串匹配,并且可以执行以下操作:

switch (base_url_string) {
    case "xxx.local":
        // Blah
        break;
    case "xxx.dev.yyy.com":
        // Blah
        break;
}

...但是同样,只有在您要匹配的完整字符串时,该方法才有效。如果base_url_string是“ yyy.xxx.local”,它将失败,而您当前的代码将与“ xxx.local”分支中的代码匹配。


更新:好吧,所以在技术上你可以使用一个switch子字符串匹配,但我不会推荐它在大多数情况下。方法如下(实时示例):

function test(str) {
    switch (true) {
      case /xyz/.test(str):
        display("• Matched 'xyz' test");
        break;
      case /test/.test(str):
        display("• Matched 'test' test");
        break;
      case /ing/.test(str):
        display("• Matched 'ing' test");
        break;
      default:
        display("• Didn't match any test");
        break;
    }
}

之所以有效,是因为JavaScript switch语句的工作方式,尤其是在两个关键方面:首先,以源文本顺序考虑大小写,其次,选择器表达式(keyword之后的位case)是按这种情况计算的表达式。求值(不是某些其他语言的常量)。因此,由于我们的测试表达式为true,因此case导致的第一个表达式true将被使用。


91
我知道它很旧,但是事实并非如此-您可以做到switch(true) { case /foo/.test(bar): ....
肖恩·金西

23
哦,天哪!Switch语句不应该那样工作。这简直是​​被打破,做那样的事情应该是非法的。
Pijusn

47
哎呀,真是邪恶。
Aditya MP

41
你们都只需要扩大视野。这是Ruby中的规范,只是true您不必将丑陋的地方放在一起,而不必在那里放丑陋的东西。
emkman 2014年

49
我喜欢这个,我不以为耻。
克里斯夫,2014年

65

RegExp不仅可以在技术上而且可以在match方法上实际用于输入字符串。

由于的输出match()是一个数组,因此我们需要检索结果的第一个数组元素。匹配失败时,函数返回null。为了避免异常错误,我们将||在访问第一个数组元素之前添加条件运算符,并针对该input属性进行测试,该属性包含输入字符串的正则表达式的静态属性

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

另一种方法是使用String()构造函数将必须只具有1个元素(没有捕获组)并且必须使用量化器(.*)捕获整个字符串的结果数组转换为字符串。如果失败,则该null对象将成为"null"字符串。不方便。

str = 'haystack';
switch (str) {
  case String(str.match(/^hay.*/)):
    console.log("Matched a string that starts with 'hay'");
    break;
}

无论如何,更优雅的解决方案是使用/^find-this-in/.test(str)with switch (true)方法,该方法仅返回布尔值,并且在不区分大小写的情况下更易于搜索。


1
pribilinsiky:您可能应该提到您的第三个解决方案(使用test())要求您具有switch(true)。
2015年

35

只需使用location.host属性

switch (location.host) {
    case "xxx.local":
        settings = ...
        break;
    case "xxx.dev.yyy.com":
        settings = ...
        break;
}

1
谢谢,+ 1,因为这是我真正应该做的
Frankenstein博士

您必须注意传递给switch语句的变量类型。它必须是一个字符串。可以确定switch ("" + location.host)
2013年

16

另一种选择是使用正则表达式匹配结果的input字段:

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

好一个。在这种情况下,任何数组属性也可以用于测试,例如.length:
Steven Pribilinskiy 2015年

6
var token = 'spo';

switch(token){
    case ( (token.match(/spo/) )? token : undefined ) :
       console.log('MATCHED')    
    break;;
    default:
       console.log('NO MATCH')
    break;;
}


->如果匹配,则三元表达式返回原始标记
---->原始标记按大小写求值

->如果未进行匹配,则三进制返回undefined
----> Case将根据undefined评估令牌,希望您的令牌不是。

三元测试可以是任何情况,例如您的情况

( !!~ base_url_string.indexOf('xxx.dev.yyy.com') )? xxx.dev.yyy.com : undefined 

===========================================

(token.match(/spo/) )? token : undefined ) 

三元表达式。

这种情况下的测试是token.match(/ spo /),它声明令牌中包含的字符串与正则表达式/ spo /的匹配(在这种情况下为文字字符串spo)。

如果表达式和字符串匹配,则结果为true并返回令牌(这是switch语句在其上操作的字符串)。

显然,记号===记号,因此switch语句被匹配并评估了大小写

如果您逐层查看它并了解Turnery测试是在switch语句“之前”进行评估的,则更容易理解,以便switch语句仅查看测试结果。


您的答案令人困惑。您可以查看和改进示例和说明吗?
falsarella 2014年

@falsarella我解释了我认为您难以理解的部分。我认为我不能举一个简单的例子。如果您有更多问题或对您的困难更具体,我可以提供更多帮助。
詹姆斯

好吧,现在我明白了。我很困惑,因为很明显这token.match(/spo/)会匹配。
falsarella 2014年

3

可能会更容易。尝试这样思考:

  • 首先在常规字符之间捕获一个字符串
  • 之后找到“案例”

// 'www.dev.yyy.com'
// 'xxx.foo.pl'

var url = "xxx.foo.pl";

switch (url.match(/\..*.\./)[0]){
   case ".dev.yyy." :
          console.log("xxx.dev.yyy.com");break;

   case ".some.":
          console.log("xxx.foo.pl");break;
} //end switch

已投票。但请注意:TypeError: url.match(...) is null
1111161171159459134 '19

1

可能为时已晚,但是我很喜欢这种情况,以防万一:)

function extractParameters(args) {
    function getCase(arg, key) {
        return arg.match(new RegExp(`${key}=(.*)`)) || {};
    }

    args.forEach((arg) => {
        console.log("arg: " + arg);
        let match;
        switch (arg) {
            case (match = getCase(arg, "--user")).input:
            case (match = getCase(arg, "-u")).input:
                userName = match[1];
                break;

            case (match = getCase(arg, "--password")).input:
            case (match = getCase(arg, "-p")).input:
                password = match[1];
                break;

            case (match = getCase(arg, "--branch")).input:
            case (match = getCase(arg, "-b")).input:
                branch = match[1];
                break;
        }
    });
};

您可以通过事件进一步处理,并传递选项列表并使用|处理正则表达式


1
对于类型安全性,我也将更|| {}改为|| [-1]或类似名称。另外,为什么new RegExp使用它,而不仅仅是斜线?
Sergey Krasilnikov,

并没有花时间去完善它。.在它起作用的那一刻,我只是继续.....我现在感到as愧。
TacB0sS

不要惊慌,那只是我的挑剔;)实际上,我什至不确定自己是对的,我尝试学习新知识。
Sergey Krasilnikov

不...您是对的...我肯定可以夸大和修饰一下。.我会尽快再获得该代码..我希望尽快:)
TacB0sS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.