Skip to content

For loops in Scala #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 5, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.baeldung.scala.forcomprehension

trait ForLoop {
// We are defining a println in a separate function in order to be able to test our iterations
def sideEffectFunction(arg: Any) = println(arg)

// Iterating an exclusive Range
def iterateRangeTo (rangeTo: Range): Unit = {
for (num <- rangeTo) {
sideEffectFunction(num)
}
}

// Iterating an inclusive Range
def iterateRangeUntil (rangeUntil: Range): Unit = {
for (num <- rangeUntil) {
sideEffectFunction(num)
}
}

// Iterating the Ranges as multiple generators
def multipleGenerators (rangeTo: Range, rangeUntil: Range): Unit = {
for {
i <- rangeTo
j <- rangeUntil
} {
sideEffectFunction(s"$i, $j")
}
}

// Iterating a Sequence of Strings
def iterateCollection (colors: Seq[String]): Unit = {
for (color <- colors) {
sideEffectFunction(color)
}
}

// Iterating a Sequences of Strings, with multiple generators
def iterateCollectionWithMultipleGenerators (colors: Seq[String]): Unit = {
for (c1 <- colors; c2 <- colors; c3 <- colors) {
sideEffectFunction(s"$c1$c2$c3 ")
}
}

// Iterating a Sequences of Strings, with multiple generators and guards
def iterateCollectionsWithGuards(colors: Seq[String]): Unit = {
for {
c1 <- colors
c2 <- colors
if c2 != c1
c3 <- colors
if c3 != c2 && c3 != c1
} {
sideEffectFunction(s"$c1$c2$c3 ")
}
}

// Iterating a Map of String to Strings
def iterateMap (map: Map[String, String]): Unit = {
for ((key,value) <- map) {
sideEffectFunction(s"""$key is for $value""")
}
}

// Iterating a Map of String to List of Strings
def iterateMapMultipleGenerators (deck: Map[String, List[String]]): Unit = {
for {
(suit, cards) <- deck
card <- cards
} {
sideEffectFunction(s"""$card of $suit""")
}
}

// Pure List iteration
def pureIteration (numbers: List[Int]): List[String] = {
for (number <- numbers) yield {
s"""$number + $number = ${number + number}"""
}
}

// Pure multiple Optional with for-comprehension
def forComprehensionWithOptionals (someIntValue: Option[Int], someStringValue: Option[String]): Option[String] = {
for {
intValue <- someIntValue
stringValue <- someStringValue
} yield {
s"""$intValue is $stringValue"""
}
}

// Pure multiple Optional with map/flatMap
def mapOptionals (someIntValue: Option[Int], someStringValue: Option[String]): Option[String] = {
someIntValue.flatMap(intValue => someStringValue.map(stringValue => s"""$intValue is $stringValue"""))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.baeldung.scala.forcomprehension

import org.junit.Assert.assertEquals
import org.junit.{Before, Test}

class ForLoopImplementation extends ForLoop {
var sideEffectResult: Seq[Any] = Nil
override def sideEffectFunction (arg: Any): Unit = {
sideEffectResult = sideEffectResult :+ arg
}

def clean(): Unit = {
sideEffectResult = Nil;
}
}

class ForLoopTest {
val forLoopTest = new ForLoopImplementation
val rangeTo: Range = 1 to 3
val rangeUntil: Range = 1 until 3
val colors = Seq("R", "G", "B")
val map = Map("R" -> "Red", "G" -> "Green", "B" -> "Blue")
val deck = Map("♣" -> List("A", "K", "Q"),
"♦" -> List("J", "10"),
"♥" -> List("9", "8", "7"),
"♠" -> List("A", "K", "J", "6"))
val numbers = List(1, 2, 3)
val someIntValue: Option[Int] = Some(10)
val someStringValue: Option[String] = Some("Ten")

@Before
def init(): Unit = {
forLoopTest.clean()
}

//givenXXX_whenYYY_thenZZZ or whenXXX_thenYYY

@Test
def gevenInclusiveRange_whenForLoop_thenIterateOverEachElement (): Unit = {
forLoopTest.iterateRangeTo(rangeTo)
val expected = Seq(1, 2, 3)
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenExclusiveRange_whenForLoop_thenIterateOverEachElement (): Unit = {
forLoopTest.iterateRangeUntil(rangeUntil)
val expected = Seq(1, 2)
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenExclusiveAndInclusiveRange_whenForLoopWithMltipleGenerators_thenCartesianProduct (): Unit = {
forLoopTest.multipleGenerators(rangeTo, rangeUntil)
val expected = Seq("1, 1", "1, 2", "2, 1", "2, 2", "3, 1", "3, 2")
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenCollection_whenForLoop_thenIterateOverEachElement (): Unit = {
forLoopTest.iterateCollection(colors)
val expected = Seq("R", "G", "B")
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenCollection_whenForLoopWithMltipleGenerators_thenAllPossibleCombinations (): Unit = {
forLoopTest.iterateCollectionWithMultipleGenerators(colors)
val expected = List("RRR ", "RRG ", "RRB ", "RGR ", "RGG ", "RGB ", "RBR ", "RBG ", "RBB ",
"GRR ", "GRG ", "GRB ", "GGR ", "GGG ", "GGB ", "GBR ", "GBG ", "GBB ",
"BRR ", "BRG ", "BRB ", "BGR ", "BGG ", "BGB ", "BBR ", "BBG ", "BBB ")
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenCollection_whenForLoopWithMltipleGeneratorsAndGuards_thenUniqueLettersCombinations (): Unit = {
forLoopTest.iterateCollectionsWithGuards(colors)
val expected = List("RGB ", "RBG ", "GRB ", "GBR ", "BRG ", "BGR ")
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenMap_whenForLoop_thenCollectionOfStrings (): Unit = {
forLoopTest.iterateMap(map)
val expected = List("R is for Red", "G is for Green", "B is for Blue")
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenMap_whenForLoopWithMltipleGenerators_thenAllCombinationsOfKeyAndValueList (): Unit = {
forLoopTest.iterateMapMultipleGenerators(deck)
val expected = List("A of ♣", "K of ♣", "Q of ♣", "J of ♦", "10 of ♦", "9 of ♥", "8 of ♥", "7 of ♥", "A of ♠", "K of ♠", "J of ♠", "6 of ♠")
assertEquals(expected, forLoopTest.sideEffectResult)
}

@Test
def gevenCollection_whenForComprehension_thenReturnedCollectionOfStrings (): Unit = {
val result = forLoopTest.pureIteration(numbers)
val expected = List("1 + 1 = 2", "2 + 2 = 4", "3 + 3 = 6")
assertEquals(expected, result)
}

@Test
def gevenOptionals_whenForComprehensionOrMap_thenReturnedOptional (): Unit = {

val resultFor = forLoopTest.forComprehensionWithOptionals(someIntValue, someStringValue)
val resultMap = forLoopTest.mapOptionals(someIntValue, someStringValue)
val expected = Some("10 is Ten")
assertEquals(expected, resultFor)
assertEquals(expected, resultMap)
assertEquals(resultFor, resultMap)
}
}