2012-03-04 14 views
35

Estoy intentando buscar en una colección de scala un elemento de una lista que coincida con algún predicado. No necesariamente necesito el valor de retorno, solo estoy probando si la lista lo contiene.Encontrar un elemento que coincida con el predicado en Scala

En Java, podría hacer algo como:

for (Object item : collection) { 
    if (condition1(item) && condition2(item)) { 
     return true; 
    } 
} 
return false; 

En maravilloso, puedo hacer algo como:

return collection.find { condition1(it) && condition2(it) } != null 

Cuál es la forma idiomática de hacer esto en Scala? Por supuesto, pude convertir el estilo de bucle de Java a Scala, pero creo que hay una forma más funcional de hacerlo.

+0

yo no me preocuparía demasiado por idiomaticidad o functionalness: las colecciones de la biblioteca Scala tienen el '' método exists' y find' (diferencia es que 'find' devuelve el elemento) que devuelven tan pronto como el elemento se encuentra. Ambos se implementan con un bucle 'var' y' while', que se ve muy similar a la implementación de java que tiene (excepto tomando el predicado como parámetro). – herman

Respuesta

42

Uso filtro:

scala> val collection = List(1,2,3,4,5) 
collection: List[Int] = List(1, 2, 3, 4, 5) 

// take only that values that both are even and greater than 3 
scala> collection.filter(x => (x % 2 == 0) && (x > 3)) 
res1: List[Int] = List(4) 

// you can return this in order to check that there such values 
scala> res1.isEmpty 
res2: Boolean = false 

// now query for elements that definitely not in collection 
scala> collection.filter(x => (x % 2 == 0) && (x > 5)) 
res3: List[Int] = List() 

scala> res3.isEmpty 
res4: Boolean = true 

Pero si todo lo que necesita es para comprobar el uso exists:

scala> collection.exists(x => x % 2 == 0) 
res6: Boolean = true 
+0

Sí, parece el método que estaba buscando. Sigue aprendiendo Scala ... Gracias. –

+7

Existe una colección 'mucho más simple {x => condición1 (x) && condición2 (x)}' – 4e6

+0

@Yep, también he añadido –

48

Comprobando si existe predicado valor coincidente

Si está interesado solamente en las pruebas si existe un valor, puede hacerlo con .... exists

scala> val l=(1 to 4) toList 
l: List[Int] = List(1, 2, 3, 4) 

scala> l exists (_>5) 
res1: Boolean = false 

scala> l exists (_<2) 
res2: Boolean = true 

scala> l exists (a => a<2 || a>5) 
res3: Boolean = true 

Otros métodos (algunos basados ​​en los comentarios):

elementos de recuento que coinciden

elementos de recuento que satisfacen el predicado (y comprobar si el recuento> 0)

scala> (l count (_ < 3)) > 0 
res4: Boolean = true 

Volviendo primer elemento coincidente

Encuentra el primer elemento que satisfaga el predicado (como lo sugirieron Tomer Gabel y Luigi Plinge, esto debería ser más eficiente porque regresa tan pronto como sea posible) ds un elemento que satisface el predicado, en lugar de recorrer toda la lista de todos modos)

scala> l find (_ < 3) 
res5: Option[Int] = Some(1) 

// also see if we found some element by 
// checking if the returned Option has a value in it 
scala> l.find(_ < 3) isDefined 
res6: Boolean = true 

Comprobando si existe valor exacto

Para el caso simple en el que estamos en realidad sólo comprobar si un elemento específico está en el lista

scala> l contains 2 
res7: Boolean = true 
+1

Si * están * interesados ​​en el valor de retorno, use findFirst. También puede obtener el conteo usando la función autodenominada. Todos toman el mismo predicado. –

+3

Es 'find', no' findFirst', pero sí eso es más eficiente que filtrar toda la lista –

+0

@LuigiPlinge Agregué la propuesta de Tomer con su corrección. ¡Gracias! –

Cuestiones relacionadas