2009-07-16 17 views

risposta

21

Non è chiaro cosa stai chiedendo - cosa ti aspetti dalla semantica del rendimento multiplo. Una cosa, però, è che probabilmente non vorrete mai usare gli indici per navigare in una lista - ogni chiamata a t (i) è O (i) da eseguire.

Così qui è una possibilità che si potrebbe chiedere per

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

Ed ecco un'altra possibilità che si potrebbe chiedere per

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

Più tardi è lo zucchero sintattico per

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 terza possibilità è che si desidera alternarli

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) 

Questo è lo zucchero sintassi per

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

Penso che voglia solo interpolare le liste. –

+0

giusto, volevo intercalarli, quindi entrambi danno lo stesso risultato: [James] val interleaved = per ((x, y) <- l zip t; r <- Lista (x, y)) resa r [Daniel] per (i <- 0-10; r <- Lista (l (i), t (i))) resa r credo che uno James' è più elegante ed emette anche Lista . Grazie mille ragazzi. –

0

Apparentemente no. Ricevo un errore di compilazione quando lo provo.

Sembra per .. la resa è un'espressione. Non puoi avere due rendimenti, dal momento che non fa realmente parte dell'espressione.

Se si desidera fornire più valori, perché non restituirli come tupla o elenco?

Ad esempio:

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

Forse resa non è il modo migliore per andare? Forse qui potrebbe essere usato un semplice array array.

+0

Non vi è alcuna differenza semantica tra l'utilizzo di rendimento e l'utilizzo di un elenco. La differenza pratica riguarda l'utilizzo della memoria, in cui la resa è più efficiente per i set di grandi dimensioni. – Christopher

5

No, non è possibile utilizzare più clausole di rendimento, ma esistono soluzioni alternative. Per esempio:

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

È possibile nido per-comprensioni, naturalmente, ma che si tradurrebbe in una lista di liste di elementi, che non credo è quello che volete.

+1

Attenzione, questa soluzione è O (n^2) –

+0

Per gli elenchi di l & t, che era, ammetto, il suo esempio. Se t & l erano matrici o funzioni, non sarebbe il caso, giusto? –

+0

A destra, per gli array l'accesso indicizzato è O (1), quindi la soluzione sarebbe O (n). –

1

Ecco una soluzione di tipo-agnostic per una, variando numero imprecisato di elementi in un numero imprecisato di liste:

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 
} 

Per 2 liste esso è sovrastampato. Si potrebbe anche chiamarlo

xproduct (List (l, t)) 
2

Le rese possono essere annidate, il che risulterebbe ...

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

in un vettore di 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 soluzione appiattito è semanticamente diversa.

Problemi correlati