scala yield cartesian-product

Scala: ¿Se puede utilizar el rendimiento varias veces con un bucle for?



yield cartesian-product (6)

Un ejemplo:

val l = List(1,2,3) val t = List(-1,-2,-3)

¿Puedo hacer algo como esto?

for (i <- 0 to 10) yield (l(i)) yield (t(i))

Básicamente quiero dar múltiples resultados para cada iteración.


Aparentemente no. Recibo un error de compilación cuando lo intento.

Parece que para ... el rendimiento es una expresión. No puedes tener dos rendimientos, ya que eso no es realmente parte de la expresión.

Si desea obtener múltiples valores, ¿por qué no cederlos como una tupla o una lista?

Por ejemplo:

for( t <- List(1,2,3); l <- List(-1,-2,-3)) yield (t, l)


Aquí hay una solución de tipo agnóstico para un número desconocido, variable de elementos en un número desconocido de listas:

def xproduct (xx: List [List[_]]) : List [List[_]] = xx match { case aa :: bb :: Nil => aa.map (a => bb.map (b => List (a, b))).flatten case aa :: bb :: cc => xproduct (bb :: cc).map (li => aa.map (a => a :: li)).flatten case _ => xx }

Para 2 Listas es overengineered. Podrías llamarlo

xproduct (List (l, t))


Los rendimientos pueden ser anidados, lo que resultaría ...

for (i <- 0 to 3) yield { for (j <- 0 to 2) yield (i,j) }

en un vector de vector:

scala.collection.immutable.IndexedSeq[scala.collection.immutable.IndexedSeq[(Int, Int)]] = Vector(Vector((0,0), (0,1), (0,2)), Vector((1,0), (1,1), (1,2)), Vector((2,0), (2,1), (2,2)), Vector((3,0), (3,1), (3,2))) for (i <- 0 to 3; j <- 0 to 2) yield (i,j)

La solución aplanada es semánticamente diferente.


No está claro qué está pidiendo, qué espera que sea la semántica de rendimiento múltiple. Sin embargo, una cosa es que probablemente nunca quieras usar índices para navegar por una lista: cada llamada a t (i) es O (i) para ejecutar.

Así que aquí hay una posibilidad que podría estar pidiendo

scala> val l = List(1,2,3); val t = List(-1,-2,-3) l: List[Int] = List(1, 2, 3) t: List[Int] = List(-1, -2, -3) scala> val pairs = l zip t pairs: List[(Int, Int)] = List((1,-1), (2,-2), (3,-3))

Y aquí hay otra posibilidad que podrías estar pidiendo

scala> val crossProduct = for (x <- l; y <- t) yield (x,y) crossProduct: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

El último es solo azúcar sintáctico para

scala> val crossProduct2 = l flatMap {x => t map {y => (x,y)}} crossProduct2: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

Una tercera posibilidad es que quieras intercalarlos.

scala> val interleaved = for ((x,y) <- l zip t; r <- List(x,y)) yield r interleaved: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)

Eso es sintaxis de azúcar para

scala> val interleaved2 = l zip t flatMap {case (x,y) => List(x,y)} interleaved2: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)


No, no puede usar varias cláusulas de rendimiento, pero hay soluciones alternativas. Por ejemplo:

for (i <- 0 to 10; r <- List(l(i), t(i))) yield r

Puede anidar las comprensiones, por supuesto, pero eso daría lugar a una lista de elementos, que no creo que sea lo que usted quiere.


Tal vez el rendimiento no es la mejor manera de ir? Tal vez se pueda usar un simple arreglo de matrices aquí.