guide - Encontrar un elemento que coincida con el predicado en Scala
scala guide style (4)
Estoy tratando de buscar en una colección scala un elemento en una lista que coincida con algún predicado. No necesito necesariamente el valor de retorno, solo pruebo si la lista lo contiene.
En Java, podría hacer algo como:
for ( Object item : collection ) {
if ( condition1(item) && condition2(item) ) {
return true;
}
}
return false;
En Groovy, 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, podría convertir el estilo de bucle Java a Scala, pero siento que hay una forma más funcional de hacerlo.
Prueba si existe un predicado de coincidencia de valores
Si solo está interesado en probar 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 comentarios):
Contando elementos coincidentes
Cuente elementos que satisfagan el predicado (y verifique si cuenta> 0)
scala> (l count (_ < 3)) > 0
res4: Boolean = true
Devolver el primer elemento coincidente
Encuentre 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 encuentra un elemento que satisface el predicado, en lugar de atravesar la Lista completa 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
Prueba si existe un valor exacto
Para el caso simple donde en realidad solo estamos verificando si un elemento específico está en la lista
scala> l contains 2
res7: Boolean = true
La forma de escala sería usar
exists
:
collection.exists(item => condition1(item) && condition2(item))
Y desde java 8 puedes usar
anyMatch
:
collection.stream().anyMatch(item -> condition1(item) && condition2(item));
que es mucho mejor que una llanura para o foreach.
Usar 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 verificar que el uso
exists
:
scala> collection.exists( x => x % 2 == 0 )
res6: Boolean = true
Filtra y existe palabras clave para obtener los valores coincidentes de las listas
val values = List(1,2,3,4,5,6,7,8,9,10,....,1000) //List -1
val factors= List(5,7) // List -2
//To get the factors of List-2 from List-1
values .filter(a => factors.exists(b => a%b == 0)) //Apply different logic for our convenience
El código dado ayuda a obtener los valores coincidentes de 2 listas diferentes