21 - nested comprehension és flatMap
¶
Különösen sokat tud lendíteni kódunk olvashatóságán, ha ,,egymásba ágyazott ciklusokat'' hajtanánk végre, azaz pl. ha több kollekciót is bejárnánk. Ennek a szintaxisa: a for comprehension belsejében az enumerátorokat pontosvesszőkkel választjuk el.
nested foreach¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Pontosvesszővel szépen egymás mellett elválasztott enumerátorokból egy beágyazott foreach
hívás lesz,
általában a
1 |
|
1 |
|
- Mi lesz ennek a for kifejezésnek a típusa? Értéke?
Válasz mutatása
- Mire fordul például a fenti példa comprehension?
1 |
|
Válasz mutatása
nested map?¶
A for yield comprehensionba is lehet pontosvesszővel több enumerátort írni.
- Ha van két string listánk, egyikben pl a színek: "Tök", "Makk" stb, másikban a számok: "hetes", "alsó", "ász" stb, hogy hozunk létre egy listát ez alapján, melyben a "Tök hetes", "Makk alsó" stb. stringek szerepelnek, minden szín-szám kombináció pont egyszer?
1 2 3 4 5 6 |
|
Válasz mutatása
- Vajon ez a fenti példakód comprehension miért nem lehet
szinek.map( { szin => szamok.map( { szam => s"$szin $szam" } ) } )
?
1 2 3 4 5 6 |
|
Válasz mutatása
Mi történik valójában...¶
... mikor egy listán ható több enumerátoros for yield comprehensiont írunk?
Ismerkedjünk meg a List[T]
osztály néhány újabb metódusával:
konkatenálás¶
:::(that: List[T): List[T]
egymás után illeszti, ,,összeragasztja'' (avagy konkatenálja) a két listát, pl. List(1,4) ::: List(2,8) = List(1,4,2,8)
.
Vegyük észre, hogy ha ehelyett a ::
operátort használnánk, akkor a List(List(1,4), 2, 8)
-at kapnánk (ennek a típusáról és hogy
miért fordul egyáltalán, később még lesz szó), egy háromelemű listát; ha pedig ezeket a listákat egymásba ágyazott mapok
értékeként kapnánk, pl. a List(1,2).map( { i => List(1,4).map( { j => i*j } ) } )
kifejezéssel, akkor mit is kapnánk?
1 |
|
Válasz mutatása
flatten¶
flatten
: List[List[T]]
-ből List[T]
-t készít, ,,feloldva'' az eggyel lentebbi szintű listákat. (Erről később még lesz szó pontosabban)
Tehát vajon pl. az előző List(List(1,4), List(2,8))
-on hívva a flatten
metódust, mi lesz a kapott érték?
1 |
|
Válasz mutatása
Vajon mi történik, ha a List(List(1,4), 2, 8).flatten
kifejezést próbáljuk kiértékelni?
Válasz mutatása
flatMap¶
flatMap[U]( f: T => List[U] ): List[U]
: a lista minden elemén kiértékeli az f
metódust, a kapott List[U]
-kat pedig konkatenálja, így lesz az érték típusa ismét List[U]
.
feladatok¶
Implementáljunk a saját listánkba flatMap
metódust, felhasználva a :::
metódust!
1 2 3 4 5 6 7 8 9 |
|
Válasz mutatása
Implementáljunk a saját listánkba flatMap
metódust, felhasználva a map
és flatten
metódusokat!
1 2 3 |
|
Válasz mutatása
Implementáljunk a saját listánkba map
metódust, felhaszválva a flatMap
metódust és az egyelemű listát létrehozó konstruktort!
1 2 3 4 5 6 7 8 |
|
Válasz mutatása
Note: ,,egyelemű listát létrehozó konstruktort'' még nem írtunk, a companion objecteknél fogjuk látni, hogy hogyan lehetséges.
Hogyan lehet pl. flatten
t készíteni a flatMap
használatával egy List[List[T]]
típusú list
listán?
1 |
|
Válasz mutatása
nested yield: flatMapek és egy map¶
Láthatjuk tehát, hogy a flatMap
, flatten
és map
metódusok, meg az egyelemű konstruktor, ami egy T
típusból készít egy List[T]
-t, szépen kifejezhetőek egymásból.
A flatMap
pedig onnan került elő, hogy amikor a Scala fordító egy for ( x1 <- c1; x2 <- c2; ...; xn <- cn ) yield E
alakú
kifejezést lát, azt a következőre írja át:
1 |
|
map
et, az összes többin pedig flatMap
et használ!
Lássuk be, hogy ez tényleg működik: értékeljük ki a for( i <- List(1,2); j <- List(1,4) ) yield i*j
kifejezést! Mi a típusa?
1 |
|
1 |
|
1 2 3 |
|
1 |
|
Válasz mutatása
1 |
|