Question

Un exemple:

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

Puis-je faire quelque chose comme ça?

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

En fait, je veux obtenir plusieurs résultats pour chaque itération.

Était-ce utile?

La solution

Il est pas clair ce que vous demandez - ce que vous attendez la sémantique de multiples rendement à. Une chose, cependant, est que vous voulez sans doute de ne jamais utiliser des index pour naviguer dans une liste -. Chaque appel à t (i) est O (i) d'exécuter

Alors, voici une possibilité que vous pourriez demander pour

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))

Et voici une autre possibilité que vous pourriez demander pour

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))

Le dernier est juste du sucre syntaxique pour

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))

Une troisième possibilité est que vous voulez les entrelacer

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)

C'est le sucre syntaxe

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)

Autres conseils

Non, vous ne pouvez pas utiliser plusieurs clauses de rendement, mais il y a des contournements. Par exemple:

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

Vous pouvez imbriquer pour-compréhensions, bien sûr, mais cela entraînerait une liste de listes d'éléments, que je ne crois pas est ce que vous voulez.

Les rendements peuvent être imbriquées, ce qui aurait pour effet ...

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

dans un vecteur de vecteur:

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 solution est aplaties sémantiquement différent.

Voici une solution de type agnostique pour un nombre inconnu, différents d'éléments dans un nombre inconnu de listes:

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
}

Pour 2 listes, il est overengineered. Vous pouvez bien appeler

   xproduct (List (l, t))

Il semble que non. Je reçois une erreur de compilation quand je l'essaye.

On dirait que pour .. le rendement est une expression. Vous ne pouvez pas avoir deux rendements, puisque ce n'est pas vraiment partie de l'expression.

Si vous souhaitez obtenir des valeurs multiples, pourquoi ne pas les céder comme tuple ou une liste?

Par exemple:

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

Peut-être rendement est pas la meilleure façon d'aller? Peut-être appending simple tableau pourrait être utilisé ici.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top