2011-07-25 8 views
48

Supongamos que tengo dos matrices:Obtener el índice del elemento actual en un método foreach de Traversable?

val ar1 = Array[String]("1", "2", "3") 
val ar2 = Array[String]("1", "2", "3", "4") 

Ahora, para cada elemento de ar1, quiero concatenar primera ese elemento con el elemento correspondiente de ar2, y luego imprimir el resultado. Una forma de hacerlo sería algo así como:

List.range(0, ar1.size).foreach(i => println(ar1(i)+ar2(i))) 

Hubiera sido mejor si había una variante foreach que me permitirá trabajar directamente con los índices de ar1 en lugar de construir primero la lista de números enteros.

¿Quizás hay una manera mejor?

+0

Véase también http://stackoverflow.com/questions/6833501/efficient-iteration-with-index-in-scala – Vadzim

Respuesta

84

Una forma muy conveniente de hacerlo es con el método zipped en tuplas. Pon dos colecciones, ¡saca dos argumentos para una función!

(ar1,ar2).zipped.foreach((x,y) => println(x+y)) 

Esto es cómodo para escribir y rápido, ya que no es necesario construir una tupla para almacenar cada par (como lo haría con (ar1 zip ar2)) que luego se tiene que desmontar de nuevo. Ambas formas de zip se detienen cuando se agota la colección más corta.

Si usted tiene algo más complicado (por ejemplo, que hay que hacer matemáticas en el índice), la solución canónica es la cremallera en el índice:

ar1.zipWithIndex.foreach{ case(x,i) => println(x+ar2(i)) } 

El método que está utilizando es más hecho rápidamente y de forma compacta de la siguiente manera, una puede ser útil:

ar1.indices.foreach(i => println(ar1(i)+ar2(i))) 

aunque esto sólo funciona si la primera colección ya no que el segundo es. También puede especificar los rangos explícitamente:

(0 until (ar1.size min ar2.size)).foreach(i => println(ar1(i)+ar2(i))) 

para solucionar este problema. (Puede ver por qué se prefieren zip y zipped a menos que lo que esté haciendo sea demasiado complicado para que esto funcione fácilmente.)

Si no es una colección paralela (y por lo general no lo es menos que llame .par), también es posible, aunque no se recomienda, para realizar un seguimiento con una variable mutable:

{ var i=-1; ar1.foreach{ x => i += 1; println(x+ar2(i)) } } 

Hay una un número muy limitado de casos en que esto es necesario (por ejemplo, si desea saltear o retroceder en alguna de las otras colecciones); Si puede evitar tener que hacer esto, generalmente terminará con un código que es más fácil de razonar.

+1

No contesto la pregunta, ya que la pregunta pregunta explícitamente sobre 'Traversable', y' Traversable' no tiene 'zipWithIndex' - que es * molesto *. –

+0

@WilfredSpringer - La pregunta _no_pregunta acerca de 'Traversable', simplemente sugiere querer usar' foreach' en algún momento. –

+0

No me malinterprete. Voy a votar tu respuesta. Solo digo que la pregunta es: "¿Obtiene el índice del elemento actual en un método foreach de * Traversable *?" Entonces parece que el punto de partida es tener un 'Traversable'; al menos así es como * I * leí la pregunta. –

4

que no tuvieron la oportunidad de probarlo, pero esto debe hacer el truco:

ar1.zip(ar2).foreach(x => println(x._1 +x._2)) 
+0

Se corrigió el doble uso de '_' al agregar una variable. –

3

zip lo hará:

ar1 zip ar2 foreach { p => println(p._1 + p._2) } 

Esto dará lugar a:

11 
22 
33 

Tenga en cuenta que no necesita [String] tipo genérico, será deducido por el compilador:

val ar1 = Array("1", "2", "3") 
val ar2 = Array("1", "2", "3", "4") 
34

Esta es la forma de bucle con un índice en idiomática Scala:

scala> List("A", "B", "C").zipWithIndex foreach { case(el, i) => 
    | println(i + ": " + el) 
    | } 
0: A 
1: B 
2: C 

Y aquí es la forma idiomática Scala de hacer lo que usted está tratando de lograr en su código:

scala> val arr1 = Array("1", "2", "3") 
arr1: Array[java.lang.String] = Array(1, 2, 3) 

scala> val arr2 = Array("1", "2", "3", "4") 
arr2: Array[java.lang.String] = Array(1, 2, 3, 4) 

scala> (arr1, arr2).zipped.map(_ + _) foreach println 
11 
22 
33 
+0

esta es también una muy buena respuesta. – Jus12

Cuestiones relacionadas