2012-03-04 10 views
35

Sto provando a cercare una scala di una voce in un elenco che corrisponde a un predicato. Non ho necessariamente bisogno del valore restituito, solo testando se la lista lo contiene.Ricerca di un elemento che corrisponde al predicato in Scala

In Java, mi potrebbe fare qualcosa di simile:

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

in Groovy, posso fare qualcosa di simile:

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

Qual è il modo idiomatico per fare questo a Scala? Naturalmente potrei convertire lo stile del ciclo Java in Scala, ma mi sembra che ci sia un modo più funzionale per farlo.

+0

io non mi preoccuperei troppo di idiomaticità o functionalness: le collezioni nella libreria Scala hanno la '' exists' e metodo find' (differenza è che 'find' restituisce l'elemento), che di ritorno, presto quando l'elemento viene trovato. Entrambe sono implementate con un ciclo 'var' e un' while', molto simile a quello che si ha con l'implementazione java (eccetto che si prende il predicato come parametro). – herman

risposta

42

Usa 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 

Ma se tutto ciò che serve è quello di controllare l'uso exists:

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

Sì, sembra il metodo che stavo cercando. Sto ancora imparando Scala ... Grazie. –

+7

Un po 'più semplice 'collection esiste {x => condition1 (x) && condition2 (x)}' – 4e6

+0

@ Sì, ho aggiunto anche questo –

48

test se il valore corrispondente predicato esiste

Se siete solo interessati a testare se esiste un valore, puoi farlo 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 

Altri metodi (alcuni basati su osservazioni):

elementi di conteggio corrispondente

elementi conteggio che soddisfano predicato (e verifica se il contatore è> 0)

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

Tornando primo elemento corrispondente

Trova il primo elemento che soddisfa il predicato (come suggerito da Tomer Gabel e Luigi Plinge questo dovrebbe essere più efficiente perché ritorna non appena finisce ds un elemento che soddisfa il predicato, piuttosto che attraversare l'intera lista in ogni caso)

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 

test se il valore esatto esiste

Per il caso semplice in cui stiamo in realtà solo controllare se un elemento specifico è nella lista

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

Se si * sono * interessati al valore di ritorno, usa findFirst. È anche possibile ottenere il conteggio utilizzando la funzione con nome. Tutti prendono lo stesso predicato. –

+3

È 'find', non' findFirst', ma sì è più efficiente del filtrare l'intero elenco –

+0

@LuigiPlinge Ho aggiunto la proposta di Tomer con la tua correzione. Grazie! –

Problemi correlati