2012-10-08 24 views
10

¿Cuál es una forma eficiente de iterar solo a través de los miembros impares de una colección en Scala, en función de la posición del índice?Iterar a través de miembros impares de la colección en Scala

Teniendo en cuenta esta lista:

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

Quiero saltar manzanas y peras, naranjas y de proceso y plátanos. ¡Gracias!

de actualización basado en las respuestas dadas:

Wow, cada uno de los tres mejores respuestas tiene mérito. Originalmente me refería a la palabra "eficiente" desde una perspectiva de sintaxis de Scala Collections, y realmente solo estaba buscando una forma elegante de crear la sublista para la iteración posterior. @Senia hace un buen trabajo al introducir la función deslizante(), ideal para este caso de uso particular, pero también me gusta el enfoque más generalizado de @ Brian usando zipWithIndex().

Sin embargo, cuando considero la redacción actual de la pregunta tal como se planteó originalmente y la eficiencia computacional de la respuesta de @ourcedelica, creo que se lleva el premio por esta.

+0

Ninguna de las respuestas hasta ahora se ha intentado a través de los miembros impares. En cambio, producen una lista de los miembros impares (que luego pueden repetirse, por supuesto). Sin embargo, debe haber una forma simple de iterar directamente sobre ellos. –

Respuesta

5

Aquí es una manera de iterar directamente sobre los impares:

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 

Si se trata de una gran colección y/o usted está haciendo muchas iteraciones, entonces querrá considerar convertirlo a un IndexedSeq primero para que el fruits(_) sea O (1). Por ejemplo:

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

Tenga en cuenta que el propio iterador está separado de la colección sobre la que se está iterando. Este es otro ejemplo que hace que más claro:

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) 

pares zipWithIndex cada elemento de lista con un índice dando:

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

filtro de los elementos impares con filter(_._2 % 2 == 1) dando:

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

en el mapa los Lista [(String, Int)] a Basta con enumerar [String] tomando el primer elemento de cada tupla con .map(_._1) entrega:

List[String] = List(oranges, bananas)

+14

Alternativamente, siempre que tenga un 'filtro' seguido de un' mapa', puede combinarlos usando 'collect', por ejemplo,' fruits.zipWithIndex.collect {case (item, idx) if idx% 2 == 1 => item} ' –

+0

¡muy agradable publicar esto de hecho! El paquete de la colección Scala justifica su uso en informática distribuida. –

1

Me gustaría proponer otro método, utilizando la recursividad, que parece hacer el menor operaciones como sea posible en mi opinión, incluso si es menos elegante que otras soluciones.

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

O, si lo que desea es procesar los miembros impares

def iterateOdd(myList:List[String]):Unit = myList match{ 
    case _::odd::tail => println(odd); iterateOdd(tail) 
    case _ => 
} 
-1
  • tengo otro enfoque para resolver este tipo de problema.
  • Podemos tomar ventaja de la lista.método de rango (inicio, fin).

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

  • Podemos generar lista de índices y podemos filtrarlos

    scala> val fruits: Lista [String] = Lista ("manzanas", "naranjas", "peras", "plátanos")

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

    re s0: Lista [String] = Lista (naranjas, plátanos)

+0

List.range (0,5) dará la lista (0,1,2,3,4) –

Cuestiones relacionadas