2010-05-24 7 views
142

Wie schreibe ich einen swtich für die folgenden Bedingungen?Switch-Anweisung für String-Matching in JavaScript

Wenn die URL "foo" enthält, dann ist settings.base_url "bar".

Das folgende ist das Erreichen der Wirkung erforderlich ist, aber ich habe das Gefühl, das in einem Schalter mehr beherrschbar sein würde:

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

Antwort

286

Sie können es nicht in einem switch, wenn Sie voll zu tun sind Zeichenkettenanpassung; das macht Teilzeichenfolge passend.(Dies ist nicht ganz wahr, wie Sean in den Kommentaren zu bedenken. Anmerkung am Ende sehen.)

Wenn Sie, dass Ihre Regex alles an der Spitze ist Abstreifen glücklich sind, dass Sie don ‚t in Ihrem Spiel vergleichen wollen, müssen Sie nicht eine Teil Spiel brauchen, und tun konnte:

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

... aber wieder, das funktioniert nur, wenn das der Sie passende komplette Zeichenfolge ist. Es würde fehlschlagen, wenn base_url_string sagen würde, "yyy.xxx.local", während Ihr aktueller Code dem im "xxx.local" Zweig entsprechen würde.


aktualisieren: Okay, Sie so technisch kann ein switch für Teilzeichenanpassung verwenden, aber ich würde es nicht in den meisten Fällen empfehlen. Hier ist, wie (live example):

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

, dass wegen der Art und Weise funktioniert JavaScript switch statements work, insbesondere zwei wesentliche Aspekte: Erstens, dass die Fälle, in Quelltext Reihenfolge berücksichtigt werden, und zweitens, dass die Wähler Ausdrücke (die Bits nach dem Schlüsselwort case) sind Ausdrücke, die ausgewertet werden, wie dieser Fall ausgewertet wird (nicht Konstanten wie in einigen anderen Sprachen). Also, da unser Testausdruck true ist, wird der erste case Ausdruck, der in true resultiert, derjenige sein, der benutzt wird.

+73

Ich weiß, es ist alt, aber das ist nicht ganz richtig - Sie können tatsächlich 'switch (true) {case/foo /.test (bar): ....' –

+2

@Sean: Ugh. Ja, Sie haben recht (lurkers: [Beispiel] (http://jsbin.com/ehabar)), aber gehen Sie nicht dorthin ... ;-) –

+0

@TJCrowder Warum empfehlen Sie nicht, eine Regex zu verwenden in den meisten Situationen? –

30

Verwenden Sie einfach die location.host Eigenschaft

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

Danke, +1 wie das ist, was ich tun sollte wirklich –

+0

Sie müssen aufpassen, über den Variablentyp, den Sie an die switch-Anweisung übergeben. Es muss * eine Zeichenfolge sein. Um sicher zu sein, können Sie 'switch (" "+ location.host)' machen. – ceving

+0

+1 für die Lösung eines XY-Problems :) – Qix

37

RegExp kann auch auf der Eingabezeichenfolge nicht nur technisch, sondern praktisch mit dem match Verfahren verwendet werden.

Da die Ausgabe des match() ein Array ist, müssen wir das erste Array-Element des Ergebnisses abrufen. Wenn die Übereinstimmung fehlschlägt, gibt die Funktion null zurück. Um einen Ausnahmefehler zu vermeiden, fügen wir vor dem Zugriff auf das erste Array-Element den || bedingten Operator hinzu und testen ihn anhand der input-Eigenschaft that is a static property of regular expressions, die die Eingabezeichenfolge enthält.

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

Ein anderer Ansatz ist es, den String() Konstruktor zu verwenden, um das resultierende Array zu konvertieren, die nur 1 Element (keine einfangenden Gruppen) und ganz Zeichenfolge muss erfaßt werden mit quanitifiers (.*) in eine Zeichenfolge aufweisen muss. Im Falle eines Fehlers wird das null Objekt ein "null" String. Nicht praktisch.

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

Wie auch immer, eine elegantere Lösung ist es, die /^find-this-in/.test(str) mit switch (true) Methode zu verwenden, die einfach einen Booleschen Wert zurückgibt und es ist einfacher, ohne Groß- und Kleinschreibung zu suchen.

+1

pribilinsiky: Sie sollten wahrscheinlich erwähnen, dass Ihre dritte Lösung (mit test()) erfordert, dass Sie wechseln (true). – traday

+0

die beste Wahl wurde als die beste Lösung in der Tat impliziert –

3
var token = 'spo'; 

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


-> Wenn das Spiel gemacht wird der ternäre Ausdruck gibt die ursprünglichen Token
----> Die ursprünglichen Token von Fall ausgewertet werden

-> Wenn das Spiel nicht gemacht das ternäre liefert undefined
----> Fall wertet das Token gegen undefined, die hoffentlich Ihr Token nicht ist.

Der ternäre Test kann zum Beispiel sein, etwas in Ihrem Fall

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

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

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

a ternary expression.

der Test ist in diesem Fall token.match ist (/ spo /), der die Übereinstimmung der Zeichenfolge gehalten in Token gegen den Regex-Ausdruck/spo/(was in diesem Fall der Literal-String spo ist).

Wenn der Ausdruck und die Zeichenfolge übereinstimmen, wird true zurückgegeben und token zurückgegeben (dies ist die Zeichenfolge, für die die switch-Anweisung ausgeführt wird).

Offensichtlich Token === Token so die switch-Anweisung übereinstimmt, und der Fall ausgewertet

Es ist leichter zu verstehen, wenn man es in Schichten sehen und verstehen, dass der Dreherei Test „vor“ die switch-Anweisung ausgewertet wird damit die switch-Anweisung nur die Ergebnisse des Tests sieht.

+0

Ihre Antwort ist verwirrend. Können Sie das Beispiel und die Erklärung überprüfen und verbessern? – falsarella

+0

@falsarella Ich habe den Teil erklärt, von dem ich dachte, dass er Probleme hat zu verstehen. Ich glaube nicht, dass ich ein einfacheres Beispiel geben kann. Wenn Sie mehr Fragen haben oder mit Ihren Schwierigkeiten spezifischer sein können, kann ich mehr helfen. – Prospero

+0

Ok, jetzt habe ich es. Ich war verwirrt, weil es offensichtlich ist, dass 'token.match (/ spo /)' übereinstimmen würde. – falsarella

10

Eine weitere Option ist input Feld eines regexp match result zu verwenden:

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

nette eins. In diesem Fall kann auch irgendeine Array-Eigenschaft für den Test verwendet werden, z. '.length:' –

2

Es ist einfacher kann.Versuchen Sie so zu denken:

  • erster Fang eine Zeichenfolge zwischen regulären Zeichen
  • nach diesem "Fall" finden

:

// '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 
0

könnte zu spät sein, und alles, aber Mir gefiel das in Fall Zuweisung :)

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

Sie können Event weiterführen, eine Optionsliste übergeben und die Regex mit | behandeln