2009-08-28 16 views
39

¿Es posible hacer coincidir un rango de valores en Scala?¿Se puede combinar un rango en Scala?

Por ejemplo:

val t = 5 
val m = t match { 
    0 until 10 => true 
    _ => false 
} 

m habría true si t fue entre 0 y 10, pero en caso contrario. Este poco no funciona, por supuesto, pero ¿hay alguna forma de lograr algo así?

+3

Tenga en cuenta que al escribir "0 hasta 10" quiere decir 0, 1, 2,. .., 9 (incluido 0, excluyendo 10). Si desea incluir 10, use "0 a 10". – Jesper

+0

Consulte una pregunta relacionada con stackoverflow: [¿Cómo puedo coincidir el patrón en un rango en Scala?] (Http://stackoverflow.com/questions/3160888/how-can-i-pattern-match-on-a-range-in -scala) –

+0

El título pregunta cómo hacer coincidir un valor de tipo 'Rango' con varias posibilidades, por ejemplo "¿Tengo' (0..5) 'o' (1..6) '?" – Raphael

Respuesta

65

Guardia usando Range:

val m = t match { 
    case x if 0 until 10 contains x => true 
    case _ => false 
} 
+0

¡Eso es muy inteligente! Por alguna razón, nunca pensé en hacerlo de esa manera ... –

27

Puede utilizar guardias:

val m = t match { 
    case x if (0 <= x && x < 10) => true 
    case _ => false 
} 
+0

En términos de rendimiento, esta solución es mejor que la solución @ alexander-azarov. Allí el Rango necesita ser inicializado seguido de un escaneo de rango. Especialmente para grandes distancias, esto puede convertirse en un problema. – Oosterman

+1

'Range.contains' es, por supuesto, anulado por lo que no necesita escanear nada! Todavía es un poco de código adicional, pero Hotspot debe alinearlo y optimizarlo sin problemas. –

2

Ésta es otra manera para que coincida con el uso de una gama:

val m = t match { 
    case x if ((0 to 10).contains(x)) => true 
    case _ => false 
} 
+0

Esto duplica la respuesta de @Alexander Azarov. – Glenn

+0

Coincidencia incorrecta para t == 10. –

2

Con estas definiciones:

trait Inspector[-C, -T] { 
    def contains(collection: C, value: T): Boolean 
    } 

    implicit def seqInspector[T, C <: SeqLike[Any, _]] = new Inspector[C, T]{ 
    override def contains(collection: C, value: T): Boolean = collection.contains(value) 
    } 

    implicit def setInspector[T, C <: Set[T]] = new Inspector[C, T] { 
    override def contains(collection: C, value: T): Boolean = collection.contains(value) 
    } 

    implicit class MemberOps[T](t: T) { 
    def in[C](coll: C)(implicit inspector: Inspector[C, T]) = 
     inspector.contains(coll, t) 
    } 

Puede hacer controles como estos:

2 in List(1, 2, 4)  // true 
2 in List("foo", 2)  // true 
2 in Set("foo", 2)  // true 
2 in Set(1, 3)   // false 
2 in Set("foo", "foo") // does not compile 
2 in List("foo", "foo") // false (contains on a list is not the same as contains on a set) 
2 in (0 to 10)   // true 

Así que el código que necesita sería:

val m = x in (0 to 10) 
Cuestiones relacionadas