2010-05-24 21 views
142

Come si scrive uno swtich per le seguenti condizioni?Istruzione switch per la corrispondenza delle stringhe in JavaScript

Se l'url contiene "pippo", quindi settings.base_url è "bar".

Di seguito è riportato ottenendo l'effetto desiderato, ma ho la sensazione che questo sarebbe più gestibile in uno switch:

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

risposta

286

Non si può fare in un switch a meno che non si sta facendo pieno corrispondenza delle stringhe; ciò corrisponde alla corrispondenza della sottostringa .(Questo non è del tuttovero, come sottolinea Sean nei commenti. Vedere nota alla fine.)

Se sei felice che il vostro regex in alto è spogliando via tutto ciò che don 't vuole confrontare in partita, non hanno bisogno di una corrispondenza sottostringa, e potrebbe fare:

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

... ma ancora una volta, che solo funziona se è la stringa completa si sta corrispondenti. Fallirebbe se base_url_string fosse, ad esempio, "yyy.xxx.local" mentre il codice corrente corrisponderebbe a quello nel ramo "xxx.local".


Aggiornamento: Okay, tecnicamente si può utilizzare un switch per la corrispondenza sottostringa, ma io non lo consiglio in molte situazioni. Ecco come (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; 
    } 
} 

che funziona a causa del modo JavaScript switch statements work, in particolare due aspetti fondamentali: in primo luogo, che i casi sono considerati in fonte di testo ordine, e in secondo luogo che le espressioni di selezione (la i bit dopo la parola chiave case) sono espressioni che vengono valutate in base alla valutazione del caso (non alle costanti come in alcune altre lingue). Pertanto, poiché la nostra espressione di test è true, la prima espressione case che risulta in true sarà quella che verrà utilizzata.

+73

So che è vecchio, ma questo non è del tutto vero - si può effettivamente fare 'switch (true) {case /foo/.test(bar): ....' –

+2

@Sean: Ugh. Sì, hai perfettamente ragione (ad esempio: [esempio] (http://jsbin.com/ehabar)), ma non andare lì ... ;-) –

+0

@TJCrowder perché non consigli di usare una regex nella maggior parte delle situazioni? –

30

Basta utilizzare la proprietà location.host

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

Grazie, +1 come questo è quello che dovrei fare davvero –

+0

Devi preoccuparti del tipo di variabile che passi all'istruzione switch. Deve * essere una stringa. Per essere sicuro di poter fare 'switch (" "+ location.host)'. – ceving

+0

+1 per risolvere un problema XY :) – Qix

37

RegExp può essere utilizzato sulla stringa di input non solo tecnicamente ma praticamente con il metodo match troppo.

Poiché l'output di match() è un array, è necessario recuperare il primo elemento di matrice del risultato. Quando la corrispondenza fallisce, la funzione restituisce null. Per evitare un errore di eccezione, aggiungeremo l'operatore condizionale || prima di accedere al primo elemento dell'array e testare la proprietà inputthat is a static property of regular expressions che contiene la stringa di 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; 
} 

Un altro approccio è quello di utilizzare il costruttore String() per convertire la matrice risultante che deve avere solo 1 elemento (nessun gruppi di cattura) e intera stringa deve essere catturato con quanitifiers (.*) ad una stringa. In caso di guasto l'oggetto null diventerà una stringa "null". Non conveniente.

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

In ogni caso, una soluzione più elegante è quella di utilizzare il /^find-this-in/.test(str) con switch (true) metodo che restituisce semplicemente un valore booleano ed è più facile per cercare, senza maiuscole e minuscole.

+1

pribilinsiky: dovresti probabilmente menzionare che la tua terza soluzione (usando test()) richiede di avere l'opzione (true). – traday

+0

la risposta più votata è stata implicita come la migliore soluzione in effetti –

3
var token = 'spo'; 

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


-> Se la partita è fatta l'espressione ternaria restituisce il token di originale
----> Il token originale viene valutata caso

-> Se la partita non è fatta il ternario restituisce un valore non definito
----> Caso valuta il token contro undefined che si spera che il token non lo sia.

Il test ternario può essere qualsiasi cosa, per esempio nel vostro caso

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

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

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

è un ternary expression.

il test in questo caso è token.match (/ spo /) che stabilisce la corrispondenza stringa tenuto in token rispetto all'espressione regex/spo/(che è la stringa letterale spo in questo caso).

Se l'espressione e la stringa corrispondono corrispondono a token vero e restituito (che è la stringa su cui opera l'istruzione switch).

Ovviamente gettone === gettone così l'istruzione switch è abbinato e il caso valutato

E 'più facile capire se si guarda a strati e capire che il test torneria viene valutato "prima" l'istruzione switch in modo che l'istruzione switch veda solo i risultati del test.

+0

La tua risposta è confusa. Riesci a rivedere e migliorare l'esempio e la spiegazione? – falsarella

+0

@falsarella ho spiegato la parte che immaginavo avessi difficoltà a capire. Non penso di poter fare un esempio più semplice. Se hai altre domande o puoi essere più specifico con le tue difficoltà, posso aiutarti di più. – Prospero

+0

Ok, ora ce l'ho. Ero confuso perché è ovvio che 'token.match (/ spo /)' avrebbe trovato una corrispondenza. – falsarella

10

Un'altra opzione è quella di utilizzare input campo di un regexp match result:

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

bello. In questo caso, qualsiasi proprietà di matrice può anche essere utilizzata per il test, ad es. '.length:' –

2

Può essere più facile.Provate a pensare in questo modo:

  • prima cattura una stringa tra i personaggi regolari
  • dopo che trovare "caso"

:

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

potrebbe essere troppo tardi e tutto, ma Mi è piaciuto in caso di assegnazione :)

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

è possibile eseguire l'evento ulteriormente e passare un elenco di opzioni e gestire la regex con |

Problemi correlati