2011-07-11 18 views
55

Mi definición del método se ve de la siguiente manera¿Cómo coincido el patrón de matrices en Scala?

def processLine(tokens: Array[String]) = tokens match { // ... 

Supongamos que deseamos saber si la segunda cadena está en blanco

case "" == tokens(1) => println("empty") 

no compila. ¿Cómo voy a hacer esto?

+0

I realmente no entiendo qué estás tratando de lograr. Compruebe si la segunda entrada de la matriz es la cadena vacía y, de ser así, ¿imprime "vacía"? En segundo lugar, su "firma de método" carece de la atribución del tipo de devolución e incluye algún código (es decir, 'tokens match {}'). – ziggystar

Respuesta

94

Si quieren perfil de compatibilidad en la matriz para determinar si el segundo elemento es la cadena vacía, puede hacer lo siguiente:

def processLine(tokens: Array[String]) = tokens match { 
    case Array(_, "", _*) => "second is empty" 
    case _ => "default" 
} 

el _* se une a cualquier número de elementos con inclusión de ninguno. Esto es similar a lo siguiente partido en listas, que es probablemente más conocido:

def processLine(tokens: List[String]) = tokens match { 
    case _ :: "" :: _ => "second is empty" 
    case _ => "default" 
} 
3

case afirmación no funciona así. Eso debería ser:

case _ if "" == tokens(1) => println("empty") 
+0

¿Qué sucede si quiero verificaciones separadas para tokens (1), tokens (2), ...? – deltanovember

+0

+1 para una solución de trabajo, pero me pregunto si el OP no esperaba una expresión compleja tipo array después de la palabra clave 'case', algo así como' (_, "", _). Decir 'caso _' es bastante aburrido, pero creo que es todo lo que puedes hacer aquí. Bien podría terminar con el partido y decir 'return tokens (1) ==" "' :-). –

+1

@Ray Toal: vea la respuesta de Ruediger Keller. –

7

La coincidencia de patrón puede no ser la elección correcta para su ejemplo. Simplemente puede hacer:

if(tokens(1) == "") { 
    println("empty") 
} 

patrón de juego es más approriate para casos como:

for(t <- tokens) t match { 
    case "" => println("Empty") 
    case s => println("Value: " + s) 
} 

que imprimen algo para cada ficha.

Editar: si desea comprobar si existe alguna señal que es una cadena vacía, también puede probar:

if(tokens.exists(_ == "")) { 
    println("Found empty token") 
} 
+1

Eso definitivamente funciona, pero parece ser la forma de procedimiento para hacer las cosas. Estaba tratando de pensar en términos funcionales – deltanovember

+0

Sí porque su pregunta requiere respuestas de procedimiento. Para un enfoque más funcional, puede asignar cada elemento a una Opción de cadena que será Ninguno cuando la cadena esté vacía. También puede envolver la línea en un mapa (o clase de caso) para dejar de trabajar explícitamente con índices. – paradigmatic

+6

@deltanovember El 'println' es lo que hace que su código sea de procedimiento. Su aparente confusión se debe al hecho de que los bloques 'if' son expresiones, no declaraciones, en Scala (es decir, devuelven un valor y, por lo tanto, son perfectamente funcionales). No hay nada intrínsecamente de procedimiento en el uso de una expresión 'if' en lugar de la coincidencia de patrones. –

4

Lo que es fresco adicional es que se puede utilizar un alias para la materia acompañada de _* con algo como

val lines: List[String] = List("Alice Bob Carol", "Bob Carol", "Carol Diane Alice") 

lines foreach { line => 
    line split "\\s+" match { 
    case Array(userName, [email protected]_*) => { /* Process user and his friends */ } 
    } 
} 
Cuestiones relacionadas