Flera generatorer
Nästad iteration.
Flera generatorer är en gratis lektion i Scala för backendutveckling och funktionell programmering på CoddyKit. Detta är lektion 3 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Scala för backendutveckling och funktionell programmering, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Scala för backendutveckling och funktionell programmering innehåller totalt 4 lektioner.
Nästad iteration i platt form
En for-comprehension kan ha flera generatorer. Var och en är en <--rad som itererar över en samling. Tillsammans producerar de alla kombinationer – en sorts nästad loop som skrivs i platt form.
object Main {
def main(args: Array[String]): Unit = {
val pairs = for {
x <- List(1, 2)
y <- List('a', 'b')
} yield (x, y)
println(pairs)
}
}Det är en kartesisk produkt
Två generatorer med storlekarna m och n producerar m × n resultat, alltså hela den kartesiska produkten. Den första generatorn är den yttre loopen och den andra den inre.
object Main {
def main(args: Array[String]): Unit = {
val grid = for {
row <- 1 to 3
col <- 1 to 3
} yield s"r$row-c$col"
println(grid.mkString(", "))
}
}Den inre generatorn kan bero på den yttre
En senare generator kan använda värden som bundits av tidigare generatorer. Detta är inte möjligt med en vanlig kartesisk produkt och är en av anledningarna till att for-comprehensions är så flexibla.
object Main {
def main(args: Array[String]): Unit = {
val upperTriangle = for {
i <- 1 to 4
j <- i to 4
} yield (i, j)
println(upperTriangle)
}
}Tre eller fler generatorer
Du kan stapla så många generatorer du vill. Med tre generatorer får du en loop nästad i tre nivåer, som producerar tupler eller beräknade värden.
object Main {
def main(args: Array[String]): Unit = {
val triples = for {
a <- 1 to 2
b <- 1 to 2
c <- 1 to 2
} yield (a, b, c)
println(triples.size + " combinations")
triples.foreach(println)
}
}Det klassiska pytagoreiska exemplet
En berömd användning är att hitta pytagoreiska tripplar. Vi itererar över tre tal och behåller bara dem där a*a + b*b == c*c gäller, genom att kombinera flera generatorer med en guard.
object Main {
def main(args: Array[String]): Unit = {
val triples = for {
a <- 1 to 20
b <- a to 20
c <- b to 20
if a * a + b * b == c * c
} yield (a, b, c)
triples.foreach(println)
}
}Så desugar det
Flera generatorer blir nästlade flatMap-anrop med ett avslutande map:
xs.flatMap(x => ys.flatMap(y => zs.map(z => ...)))
Varje extra generator lägger till ytterligare en nästad nivå.
object Main {
def main(args: Array[String]): Unit = {
val sugar = for {
x <- List(1, 2)
y <- List(3, 4)
} yield x * y
val desugared = List(1, 2).flatMap(x => List(3, 4).map(y => x * y))
println(sugar == desugared)
}
}Blanda generatorer och guards
Du kan fritt blanda generatorer och guards. En guard som placeras mellan två generatorer sållar bort yttre värden innan den inre loopen ens körs.
object Main {
def main(args: Array[String]): Unit = {
val result = for {
x <- 1 to 5
if x % 2 == 1
y <- 1 to 5
if y > x
} yield (x, y)
println(result)
}
}Platta ut nästlade samlingar
När du har en samling av samlingar plattar två generatorer naturligt ut den: den första itererar över den yttre samlingen och den andra över varje inre samling.
object Main {
def main(args: Array[String]): Unit = {
val matrix = List(List(1, 2), List(3, 4), List(5, 6))
val flat = for {
row <- matrix
value <- row
} yield value
println(flat)
}
}Bygga ett strängrutnät
Flera generatorer passar utmärkt för att generera strukturerade resultat, till exempel koordinater eller en multiplikationstabell.
object Main {
def main(args: Array[String]): Unit = {
val table = for {
i <- 1 to 3
j <- 1 to 3
} yield s"$i*$j=${i * j}"
println(table.grouped(3).map(_.mkString(" ")).mkString("\n"))
}
}Kombinera samlingar av olika storlek
Generatorerna behöver inte ha samma längd. Varje kombination av ett element från varje samling produceras.
object Main {
def main(args: Array[String]): Unit = {
val sizes = List("S", "M", "L")
val colors = List("red", "blue")
val products = for {
s <- sizes
c <- colors
} yield s"$c-$s"
println(products)
}
}Ordningen påverkar resultatsekvensen
Om du byter ordning på generatorerna får du samma uppsättning kombinationer, men deras ordning ändras eftersom den sista generatorn varierar snabbast.
object Main {
def main(args: Array[String]): Unit = {
val ab = for { x <- List(1, 2); y <- List(9, 8) } yield (x, y)
val ba = for { y <- List(9, 8); x <- List(1, 2) } yield (x, y)
println(ab)
println(ba)
}
}Snabb kontroll
Hur många tupler producerar for { x <- List(1,2,3); y <- List('a','b') } yield (x, y)?
Sammanfattning
Du har lärt dig om flera generatorer:
- Varje
<--rad lägger till en nivå av nästad iteration - Tillsammans producerar de den kartesiska produkten
- Inre generatorer kan bero på yttre bundna värden
- De desugar till nästlade
flatMapsamt ett avslutandemap - Generatorernas ordning ändrar resultatens ordning
Lär dig Scala med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 39
- Lektioner
- 143
Vanliga frågor
Är lektionen ”Flera generatorer” gratis?
Ja – hela texten till ”Flera generatorer” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Scala för backendutveckling och funktionell programmering, kan Ni uppgradera till CoddyKit PRO. Kursen i Scala för backendutveckling och funktionell programmering innehåller totalt 4 lektioner.
Vad lär jag mig i ”Flera generatorer”?
Nästad iteration. Ni övar på Scala för backendutveckling och funktionell programmering med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Scala för backendutveckling och funktionell programmering?
Du behöver inga förkunskaper. Utbildningen i Scala för backendutveckling och funktionell programmering på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.
Hur lång tid tar lektionen ”Flera generatorer”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Scala för backendutveckling och funktionell programmering-lektionen?
Ja. Varje Scala för backendutveckling och funktionell programmering-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Desugaring av for
- Filtrera med if
- Flera generatorer
- Använda Option och Future