2012-10-08 11 views
10

Che cosa è un modo efficace per scorrere solo i membri dispari di una raccolta in Scala, in base alla posizione dell'indice?Iterate attraverso i membri dispari della raccolta in Scala

Dato questo elenco:

val fruits: List[String] = List("apples", "oranges", "pears", "bananas") 

voglio saltare mele e pere e arance di processo e banane. Grazie!

Aggiornamento in base alle risposte date:

Wow, ciascuna delle prime tre risposte ha merito. Originariamente intendevo la parola "efficiente" dal punto di vista della sintassi di Scala Collections, e stavo davvero cercando un modo intelligente per creare la sottolista per l'iterazione successiva. @Senia fa un buon lavoro introducendo la funzione sliding(), ottima per questo particolare use case, ma mi piace anche l'approccio più generalizzato di @ Brian usando zipWithIndex().

Tuttavia, quando considero l'attuale formulazione della domanda come originariamente richiesta e l'efficienza computazionale della risposta di @ sourcedelica, penso che prenda il premio per questo.

+0

Nessuna delle risposte fino ad ora interagisce tra i membri dispari. Invece, producono una lista dei membri dispari (che possono quindi essere iterati sopra, ovviamente). Deve esserci un modo semplice di iterare direttamente sopra di loro, però? –

risposta

5

Ecco un modo per scorrere direttamente su quelli dispari:

val fruits: List[String] = List("apples", "oranges", "pears", "bananas") 
//> fruits : List[String] = List(apples, oranges, pears, bananas) 

val oddFruitsIterator = 
    Iterator.from(1, 2).takeWhile(_ < fruits.size).map(fruits(_)) 
//> oddFruits : Iterator[String] = non-empty iterator 

oddFruitsIterator.foreach(println)      
//> oranges 
//> bananas 

Se si tratta di una grande collezione e/o stai facendo un sacco di iterazioni, quindi ti consigliamo di convertirlo prima in un IndexedSeq in modo che lo fruits(_) sia O (1). Ad esempio:

val fruitsIs = fruits.toIndexedSeq 
val oddFruits = Iterator.from(1, 2).takeWhile(_ < fruitsIs.size).map(fruitsIs(_)) 

Si noti che l'iteratore stesso è separato dalla raccolta su cui sta iterando. Ecco un altro esempio che rende più chiaro che:

scala> val oddSeqIterator = 
    (seq: Seq[String]) => Iterator.from(1, 2).takeWhile(_ < seq.size).map(seq(_)) 
oddSeqIterator: Seq[String] => Iterator[String] = <function1> 

scala> val fruits: List[String] = List("apples", "oranges", "pears", "bananas") 
fruits: List[String] = List(apples, oranges, pears, bananas) 

scala> oddSeqIterator(fruits) 
res0: Iterator[String] = non-empty iterator 

scala> res0.foreach(println) 
oranges 
bananas 
15
scala> List("apples", "oranges", "pears", "bananas").drop(1).sliding(1, 2).flatten.toList 
res0: List[java.lang.String] = List(oranges, bananas) 
11
val fruits: List[String] = List("apples", "oranges", "pears", "bananas") 

fruits.zipWithIndex.filter(_._2 % 2 == 1).map(_._1) 

res0: List[String] = List(oranges, bananas) 

zipWithIndex accoppiamenti ogni elemento nell'elenco con un indice che fornisce:

List[(String, Int)] = List((apples,0), (oranges,1), (pears,2), (bananas,3))

filtro elementi dispari con filter(_._2 % 2 == 1) dando:

List[(String, Int)] = List((oranges,1), (bananas,3))

map elenco [(String, Int)] a basta List [String] prendendo il primo elemento di ogni tupla con .map(_._1) dono:

List[String] = List(oranges, bananas)

+14

In alternativa, ogni volta che si ha un 'filter' seguito da una' map', è possibile combinarli usando 'collect', ad esempio' fruits.zipWithIndex.collect {case (item, idx) if idx% 2 == 1 => item} ' –

+0

post molto bello questo in atto! Il pacchetto di raccolta Scala giustifica il suo utilizzo nel calcolo distribuito. –

1

vorrei proporre un altro metodo, utilizzando la ricorsione, che sembra fare meno operazioni possibili, a mio parere, anche se è meno elegante di altre soluzioni.

def iterateOdd(myList:List[String]):List[String] = myList match{ 
    case _::odd::tail => odd::iterateOdd(tail) 
    case _ => Nil 
} 

Oppure, se si desidera solo per processare i membri dispari

def iterateOdd(myList:List[String]):Unit = myList match{ 
    case _::odd::tail => println(odd); iterateOdd(tail) 
    case _ => 
} 
-1
  • ho un altro approccio per risolvere questo tipo di problema.
  • Possiamo usufruire di Elenco.range (inizio, fine) metodo.

List.range (0,5) darà List (0,1,2,3,4)

  • Siamo in grado di generare l'elenco di indici e li possiamo filtrare

    scala> val fruits: List [String] = List ("mele", "arance", "pere", "banane")

    scala> List.range (0, fruits.length) .filter (_% 2 ! = 0) .map (x => fruits (x))

    re s0: List [String] = List (arance, banane)

+0

List.range (0,5) darà List (0,1,2,3,4) –

Problemi correlati