web-dev-qa-db-fra.com

Instruction Switch pour la correspondance des chaînes en JavaScript

Comment puis-je écrire un swtich pour le conditionnel suivant?

Si l'URL contient "foo", settings.base_url est "bar".

Ce qui suit permet d’obtenir l’effet recherché, mais j’ai le sentiment que cela serait plus facile à gérer avec un commutateur:

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/"
    };
}
172
Dr. Frankenstein

Vous ne pouvez le faire dans un switch que si vous faites une correspondance complète de chaînes ; cela fait une correspondance de sous-chaîne . [Ce n'est pas tout à fait vrai, comme le souligne Sean dans les commentaires. Voir la note à la fin.)

Si vous êtes satisfait que votre regex au sommet supprime tout ce que vous ne voulez pas comparer dans votre correspondance, vous n'avez pas besoin d'une correspondance de sous-chaîne et vous pourriez faire:

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

... mais encore une fois, cela ne fonctionne que si c'est la chaîne complète que vous correspondez. Cela échouerait si base_url_string était, par exemple, "yyy.xxx.local" alors que votre code actuel correspond à celui de la branche "xxx.local".


Mise à jour : D'accord, donc techniquement vous pouvez utilisez un switch pour la correspondance de sous-chaîne, mais je ne le recommanderais pas. dans la plupart des situations. Voici comment ( exemple en direct ):

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

Cela fonctionne à cause de la manière dont JavaScript les instructions switch fonctionnent , en particulier deux aspects essentiels: premièrement, que les cas soient considérés dans l’ordre texte source, et deuxièmement que les expressions de sélecteur (les bits après le mot-clé case) sont expressions qui sont évaluées au cas où ce cas est évalué (pas des constantes comme dans d'autres langues). Donc, puisque notre expression de test est true, la première expression case qui résulte en true sera celle qui sera utilisée.

330
T.J. Crowder

RegExp peut être utilisé sur la chaîne d'entrée non seulement techniquement mais aussi pratiquement avec la méthode match.

Comme la sortie de la match() est un tableau, nous devons récupérer le premier élément de tableau du résultat. Lorsque la correspondance échoue, la fonction retourne null. Pour éviter une erreur d’exception, nous ajouterons l’opérateur conditionnel || avant d’accéder au premier élément du tableau et de tester la propriété input, propriété statique des expressions régulières qui contient la chaîne d'entrée.

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

Une autre approche consiste à utiliser le constructeur String() pour convertir le tableau résultant, qui ne doit comporter qu'un seul élément (aucun groupe de capture) et la chaîne entière doit être capturée avec quanitifiers (.*) en chaîne. En cas d'échec, l'objet null deviendra une chaîne "null". Pas pratique.

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

Quoi qu'il en soit, une solution plus élégante consiste à utiliser la méthode /^find-this-in/.test(str) avec switch (true), qui renvoie simplement une valeur booléenne et facilite la recherche sans distinction de casse.

50
Steven Pribilinskiy

Il suffit d'utiliser la propriété location.Host

switch (location.Host) {
    case "xxx.local":
        settings = ...
        break;
    case "xxx.dev.yyy.com":
        settings = ...
        break;
}
34
Sean Kinsey

Une autre option consiste à utiliser le champ input d'un résultat d'une correspondance d'expression régulière :

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;
}
12
Mitar
var token = 'spo';

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


-> Si la correspondance est faite, l'expression ternaire renvoie le jeton d'origine
----> Le jeton d'origine est évalué par cas

-> Si la correspondance n'est pas faite, le ternaire retourne indéfini
----> Case évalue le jeton par rapport à indéfini, ce qui, espérons-le, ne le sera pas.

Le test ternaire peut être n'importe quoi, par exemple dans votre cas

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

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

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

est un expression ternaire.

Le test dans ce cas est token.match (/ spo /) qui indique la correspondance de la chaîne contenue dans token par rapport à l'expression régulière/spo/(qui est la chaîne littérale spo dans ce cas).

Si l'expression et la chaîne correspondent, le résultat est true et renvoie un jeton (c'est-à-dire la chaîne sur laquelle l'instruction switch est utilisée).

Evidemment jeton === jeton pour que l'instruction switch soit mise en correspondance et que le cas soit évalué

Il est plus facile de comprendre si vous le regardez dans les couches et comprenez que le test de retournement est évalué "AVANT" l’instruction switch de sorte que l’instruction switch ne voit que les résultats du test.

4
Arcabard

Cela peut être plus facile. Essayez de penser comme ça:

  • d'abord attraper une chaîne entre les caractères normaux
  • après cette découverte "cas"

:

// '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
Geery.S

Peut-être trop tard et tout, mais j'ai aimé cela en cas d'affectation :)

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

vous pouvez éventuellement aller plus loin, passer une liste d’options et manipuler la regex avec |

1
TacB0sS