2011-05-08 17 views
15

Digamos que tengo una variable xy quiero verificar si es igual a cualquiera de los múltiples valores a, b, c, d, e (Me refiero a == igualdad, no identidad).En Scala, ¿existe una forma simple y clara de comparar un valor con múltiples valores

En una consulta SQL el mismo concepto se maneja con

WHERE x IN (a, b, c, d, e). 

¿Hay algo equivalente en Scala que es tan sencillo como eso? Sé que de otra manera es posible hacerlo en una línea con una expresión compleja como construir un HashSet y verificar la existencia en el conjunto, pero preferiría usar una construcción simple si está disponible.

Respuesta

20

yo preferiría contains(a) sobre exists(_ == a):

scala> List(3, 4, 5) contains 4 
res0: Boolean = true 

scala> List(3, 4, 5) contains 6 
res1: Boolean = false 

Actualización: contains se define en SeqLike, por lo que los trabajos anteriores con cualquier secuencia.

Actualización 2: Esta es la definición de contains en SeqLike:

def contains(elem: Any): Boolean = exists (_ == elem) 
+1

Disculpa, te rechacé, porque pensé que 'contiene' solo funcionaría con identidad, no con igualdad. Yo te voté y comencé a escribir una prueba más larga en mi respuesta, pero en cambio probé que estaba equivocado. Lo siento. :) –

+0

@user Y voté tu respuesta porque como puedes ver en mi segunda actualización 'contains (a)' es solo azúcar para 'exists (_ == a)' por lo que nuestras respuestas son equivalentes. –

+0

Puede que solo sea azúcar, pero soy dulce, y como editó su respuesta, pude corregir mi voto. (Scala es solo azúcar sintáctica para Java, que es azúcar sintáctica para ensamblador ...). –

5

existe:

List (3, 4, 5).exists (_ == 4) 
// res20: Boolean = true 

hallazgo y el filtro se acercan:

List (3, 4, 5).find (_ == 4) 
// res16: Option[Int] = Some(4) 
List (3, 4, 5).filter (_ == 4) 
// res17: List[Int] = List(4) 

Mi primera respuesta fue, como otras respuestas, para usar contener:

List (3, 4, 5).contains (4) 

pero luego pensé , solo funcionaría para valores encuadrados como 4, no para clases, que distinguen identidad e igualdad. Para demostrarlo, escribí una pequeña clase, que resultó me equivocada: :)

class Ue (val i: Int) { 
    override def equals (other: Any) = other match { 
    case o: Ue => i == o.i 
    case _ => false } 
} 

val a = new Ue (4) 
// a: Ue = [email protected] 
val b = new Ue (4) 
// b: Ue = [email protected] (no identity) 
a == b 
// res110: Boolean = true (surprise?) 
a.equals (b) 
// res112: Boolean = true (expected) 
a.eq (b) 
// res113: Boolean = false (expected) 
List (a).contains (b)  
// res119: Boolean = true (surprise) 
List (a).exists (_ == b) 
// res120: Boolean = true (expected) 
List (a).exists (_ .eq (b)) 
// res121: Boolean = false (expected) 

veo, tengo que usar es igual a/eq/== más a menudo, para obtener las distinciones en mi cerebro.

List (3, 4, 5).contains (4) 

es la respuesta más fácil.

23

podría implementar un operador in de la siguiente manera:

scala> implicit def anyWithIn[A](a: A) = new { 
    | def in(as: A*) = as.exists(_ == a) 
    | } 
anyWithIn: [A](a: A)java.lang.Object{def in(as: A*): Boolean} 

scala> 5 in (3, 4, 9, 11) 
res0: Boolean = false 

scala> 5 in (3, 4, 9, 11, 5) 
res1: Boolean = true 
+2

Eso es hermoso. Va directamente a mi propio conjunto de extensiones estándar que terminan en todos mis proyectos, y podría decirse que incluye la inclusión de biblioteca estándar –

+1

. Vea mi respuesta sobre cómo hacer esto de la * otra * forma: pimp un 'A => Booleano' para que puede escribir '5 ∈: Set (1, 2, 3, 4, 5)' –

+1

¡Aseado! Esto debería estar incorporado en la próxima versión de Scala. Pero tal como está, requeriría importar explícitamente o heredar la conversión implícita en cualquier lugar que se necesite, así que por ahora voy con la técnica Lista/contiene. – Gigatron

12

Teniendo en cuenta que un Set[A] es también un A => Boolean, puede simplemente decir:

Set(a, b, c, d, e) apply x 

En realidad es bastante agradable para definir un poco de azúcar pimpin para esto:

class PredicateW[A](self : A => Boolean) { 
    def ∈:(a : A) = self apply a 
} 
implicit def pred2wrapper[A](p : A => Boolean) = new PredicateW(p) 

entonces se puede escribir el código de este modo:

x ∈: Set(a, b, c, d, e) 
+2

Otra solución ordenada, gracias. ¡Pero no tengo el símbolo '∈' en mi teclado estadounidense! – Gigatron

8

Al sintetizar todas las otras respuestas, que han llegado con la respuesta correcta :

implicit def anyWithIn[A](a: A) = new { 
    def ∈(as: A*) = as.contains(a) 
} 
anyWithIn: [A](a: A)java.lang.Object{def ?(as: A*): Boolean} 

5 ∈ (1,3,5) 
res1: Boolean = true 

Ta-da.

+1

+1 para beeing en negrita. – Landei

+0

Oye, lo defenderé como demostrablemente mejor que cualquier otra respuesta dada hasta ahora (más legible que la solución de missingfaktor, más pimplicious que la de Oxbow_lakes, más comprensible y la de Dan ...) – Malvolio

4

Set(a, b, c, d, e)(x) funciona también. Dejaré las razones de ello como un ejercicio para el lector. :-)

0
class Ue (val i: Int) { 
    override def equals (other: Any) = other match { 
    case o: Ue => i == o.i 
    case _ => false } 
} 

val a = new Ue (4) 
// a: Ue = [email protected] 
val b = new Ue (4) 
// b: Ue = [email protected] (no identity) 
a == b 
// res110: Boolean = true (surprise?) 
a.equals (b) 
// res112: Boolean = true (expected) 
a.eq (b) 
// res113: Boolean = false (expected) 
List (a).contains (b)  
// res119: Boolean = true (surprise) 
List (a).exists (_ == b) 
// res120: Boolean = true (expected) 
List (a).exists (_ .eq (b)) 
// res121: Boolean = false (expected) 
Cuestiones relacionadas