2010-05-24 12 views
142

¿Cómo escribo un swtich para el siguiente condicional?Cambio de declaración para la coincidencia de cadenas en JavaScript

Si la url contiene "foo", entonces settings.base_url es "bar".

La siguiente está logrando el efecto deseado, pero tengo una sensación de que esto sería más manejable en un interruptor:

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

Respuesta

286

Usted no puede hacerlo de una switch menos que esté haciendo completa coincidencia de cadena; eso está haciendo subcadena correspondiente.(Esto no es bastantecierto, como señala Sean en los comentarios. Ver nota al final.)

Si está satisfecho de que su expresión regular en la parte superior está quitando todo lo que Don 't desea comparar en el partido, que no necesitan una subcadena coincidente, y podrían hacer:

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

... pero una vez más, que sólo funciona si esa es la secuencia completa que estés a juego. Fallaría si base_url_string fuera, por ejemplo, "yyy.xxx.local", mientras que su código actual coincidiría con el de la rama "xxx.local".


actualización: Bueno, por lo que técnicamente puede utilizar un switch para la coincidencia de subcadena, pero yo no lo recomendaría en la mayoría de las situaciones. He aquí cómo (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; 
    } 
} 

que funciona debido a la forma JavaScript switch statements work, en particular dos aspectos fundamentales: En primer lugar, que los casos se consideran en fuente de texto orden, y segundo, que las expresiones de selector (la bits después de la palabra clave case) son expresiones que se evalúan a medida que se evalúa ese caso (no constantes como en otros idiomas). Entonces, dado que nuestra expresión de prueba es true, la primera expresión case que resulte en true será la que se use.

+73

Sé que es viejo, pero esto no es del todo cierto - en realidad se puede hacer 'cambiar (verdadero) {caso /foo/.test(bar): ....' –

+2

@Sean: Ugh. Sí, tiene toda la razón (lurkers: [ejemplo] (http://jsbin.com/ehabar)), pero no vaya allí; ;-) –

+0

@TJCrowder ¿por qué no recomienda usar una expresión regular? en la mayoría de las situaciones? –

30

sólo tiene que utilizar la propiedad location.host

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

Gracias, +1, ya que esto es lo que debería hacer realmente –

+0

Debe tener cuidado con el tipo de variable que pasa a la instrucción de cambio. * Debe * ser una cadena. Para asegurarse de que puede hacer 'switch (" "+ location.host)'. – ceving

+0

+1 para resolver un problema XY :) – Qix

37

RegExp se puede utilizar en la cadena de entrada no sólo técnicamente sino prácticamente con el método match también.

Como la salida de match() es una matriz, necesitamos recuperar el primer elemento de matriz del resultado. Cuando falla la coincidencia, la función devuelve null. Para evitar un error de excepción, agregaremos el operador condicional || antes de acceder al primer elemento del conjunto y probarlo en la propiedad inputthat is a static property of regular expressions que contiene la cadena de entrada.

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

Otro enfoque es utilizar el constructor String() para convertir la matriz resultante que debe tener solamente 1 elemento (no hay grupos de captura) y la cadena de conjunto debe ser capturada con quanitifiers (.*) a una cadena. En caso de falla, el objeto null se convertirá en una cadena "null". No conveniente.

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

De todos modos, una solución más elegante es usar el /^find-this-in/.test(str) con switch (true) método que simplemente devuelve un valor booleano y es más fácil de buscar sin mayúsculas y minúsculas.

+1

pribilinsiky: probablemente debas mencionar que tu tercera solución (usando test()) requiere que tengas el switch (verdadero). – traday

+0

la respuesta más votada fue implícita como la mejor solución, de hecho –

3
var token = 'spo'; 

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


-> Si el partido se hizo la expresión ternaria devuelve el original símbolo
----> El símbolo original se evalúa por caso

-> Si el partido no se hace el ternario devuelve indefinido
----> Case evalúa el token contra indefinido, lo que esperamos que su token no lo haga.

La prueba ternario puede ser cualquier cosa, por ejemplo, en su caso

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

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

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

es una ternary expression.

la prueba en este caso es token.match (/ SPO /) que establece el partido mantuvo la cadena en token contra la expresión de expresiones regulares/spo/(que es el spo de cadena literal en este caso).

Si la expresión y la cadena coinciden, da como resultado verdadero y devuelve el token (que es la cadena en la que está operando la instrucción switch).

Obviamente símbolo === símbolo por lo que la sentencia switch se compara y evalúa el caso

Es fácil de entender si se mira en capas y entiende que la prueba se evalúa al torno "antes" de la sentencia switch de modo que la instrucción switch solo vea los resultados de la prueba.

+0

Su respuesta es confusa. ¿Puedes revisar y mejorar el ejemplo y la explicación? – falsarella

+0

@falsarella Le expliqué la parte que imaginaba que tenía problemas para entender. No creo que pueda hacer un ejemplo más simple. Si tiene más preguntas o puede ser más específico con sus dificultades, puedo ayudarlo más. – Prospero

+0

Ok, ahora lo tengo. Estaba confundido porque es obvio que 'token.match (/ spo /)' coincidiría. – falsarella

10

Otra opción es utilizar input campo de 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

nice one. En este caso, cualquier propiedad de matriz también se puede usar para la prueba, p. '.length:' –

2

Puede ser más fácil.Trate de pensar de esta manera:

  • primera captura una cadena entre los personajes regulares
  • después de que encontrar "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

podría ser demasiado tarde y todo, pero Me gustó esto en caso de asignación :)

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

podría llevarlo más lejos, pasar una lista de opciones y manejar la expresión regular con |

Cuestiones relacionadas