Оператор переключения для сопоставления строк в JavaScript - PullRequest
170 голосов
/ 24 мая 2010

Как мне написать swtich для следующего условия?

Если url содержит"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/"
    };
}

Ответы [ 7 ]

327 голосов
/ 24 мая 2010

Вы не можете сделать это за switch, если не выполните полное сопоставление строк;это делает подстрока соответствие. (Это не вполне правда, как указывает Шон в комментариях. См. примечание в конце.)

Если вы счастливы, что ваше регулярное выражение отбрасывает все, что вы не хотите сравнивать в своем совпадении, вам не нужно совпадение подстроки, и вы можете сделать:

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

... но опять же, это работает, только если вы соответствуете строке complete .Сбой, если бы 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 работают , в частности два ключевых аспекта: во-первых, этослучаи рассматриваются в порядке исходного текста , а во-вторых, что выражения селектора (биты после ключевого слова case) являются выражениями , которые оцениваются при оценке этого случая (не константы)как и в некоторых других языках).Так как наше тестовое выражение - true, первое case выражение, которое приводит к true, будет тем, которое будет использовано.

49 голосов
/ 18 сентября 2013

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) с switch (true), который просто возвращает логическое значение, и его легче искать без учета регистра.

34 голосов
/ 24 мая 2010

Просто используйте свойство location.host

switch (location.host) {
    case "xxx.local":
        settings = ...
        break;
    case "xxx.dev.yyy.com":
        settings = ...
        break;
}
12 голосов
/ 25 июля 2014

Другой вариант - использовать 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;
}
3 голосов
/ 18 июня 2017

Это может быть проще. Попробуйте подумать так:

  • сначала поймать строку между обычными символами
  • после этого найдите "кейс"

// '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
3 голосов
/ 28 февраля 2014
var token = 'spo';

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


-> Если совпадение выполнено, троичное выражение возвращает исходный токен
----> Исходный токен оценивается регистром

-> Если совпадение не установлено, троичный символ возвращается неопределенным
----> Case сравнивает токен с неопределенным, который, надеюсь, не является вашим токеном.

Тройной тест может быть чем угодно, например, в вашем случае

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

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

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

- это троичное выражение .

Тестом в этом случае является token.match (/ spo /), который устанавливает соответствие строки, содержащейся в токене, с выражением регулярного выражения / spo / (в данном случае это буквальная строка spo).

Если выражение и строка совпадают, это приводит к истине и возвращает токен (то есть строку, над которой работает оператор switch).

Очевидно, токен === токен, так что оператор switch сопоставляется, а регистр вычисляется

Проще понять, если вы посмотрите на него послойно и поймете, что тест Turnery оценивается "ДО" оператора switch, так что оператор switch видит только результаты теста.

1 голос
/ 15 января 2018

Возможно, уже слишком поздно и все, но мне понравилось это в случае присваивания:)

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

вы могли бы взять его дальше, передать список параметров и обработать регулярное выражение с помощью |

...