Znajdowanie elementu pasującego do predykatu w Scali

Próbuję przeszukać kolekcję Scali pod kątem pozycji na liście, która pasuje do jakiegoś predykatu. Niekoniecznie potrzebuję zwracanej wartości, tylko sprawdzam, czy lista ją zawiera.

W Javie mogę zrobić coś takiego:

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

W Groovy mogę zrobić coś takiego:

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

Jaki jest idiomatyczny sposób, aby to zrobić w Scali? Mógłbym oczywiście przekonwertować styl Java loop do Scali, ale czuję, że jest bardziej funkcjonalny sposób, aby to zrobić.

Author: Jeff Storey, 2012-03-04

4 answers

Użyj filtra:

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

Ale jeśli wystarczy sprawdzić użyj exists:

scala> collection.exists( x => x % 2 == 0 )
res6: Boolean = true
 58
Author: om-nom-nom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-04 16:32:01

Sprawdzanie, czy istnieje predykat dopasowujący wartość

Jeśli jesteś po prostu zainteresowany testowaniem, czy wartość istnieje, możesz to zrobić za pomocą.... 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

Inne metody (niektóre na podstawie komentarzy):

Liczenie pasujących elementów

Policz elementy, które spełniają predykat (i sprawdź, czy count > 0)

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

Zwracanie pierwszego dopasowanego elementu

Znajdź pierwszy element, który spełnia predykat (zgodnie z sugestią Tomera Gabela i Luigiego Plinge powinno to być bardziej efektywny, ponieważ zwraca, gdy tylko znajdzie jeden element spełniający predykat, zamiast i tak przemierzać całą listę)

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

Sprawdzanie, czy istnieje dokładna wartość

Dla prostego przypadku, w którym sprawdzamy tylko, czy jeden konkretny element jest na liście

scala> l contains 2
res7: Boolean = true
 55
Author: Paolo Falabella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-29 09:04:54

Sposobem Scali byłoby użycie exists:

collection.exists(item => condition1(item) && condition2(item))

A od Javy 8 można używać anyMatch:

collection.stream().anyMatch(item -> condition1(item) && condition2(item));
Co jest znacznie lepsze niż zwykły for lub foreach.
 0
Author: senjin.hajrulahovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 14:54:27

Filter and exists keywords to get the matching values from List

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

Podany kod pomaga uzyskać pasujące wartości z 2 różnych list

 0
Author: Yuvaraj S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-15 11:18:54