I want to generate a combination of some values as in the code below:
object ContinueGenerate {
val foods = List("A", "B", "C")
val places = List("P1", "P2", "P3")
val communities = List("C1", "C2", "C3", "C4")
case class Combination(food: String, place: String, community: String)
def allCombinations() = {
for {
food <- foods; place <- places; community <- communities
} yield Combination(food, place, community)
}
def main(args: Array[String]) {
allCombinations foreach println
}
}
However the problem with this approach is that, all the data is generated at once. This is big problem when the size of foods, places and communities becomes very large. Also there could be other parameters other than these three.
So I want to be able generate combinations, in a continuation style, such that a combination is generated only when it is requested.
What would be an idiomatic Scala way of doing that ?
You use streams:
object ContinueGenerate {
val foods = Stream("A", "B", "C")
val places = Stream("P1", "P2", "P3")
val communities = Stream("C1", "C2", "C3", "C4")
case class Combination(food: String, place: String, community: String)
def allCombinations() = {
for {
food <- foods; place <- places; community <- communities
} yield Combination(food, place, community)
}
def main(args: Array[String]) {
allCombinations foreach println
}
}
A Stream caches all the data. If you only want to iterate once, use Iterator instead, which should garbage-collect already traversed elements.
You can do this by using a View over each list. In the code below I've added a side effect so it is visible when the yield gets called for each element.
val foods = List("A", "B", "C")
val places = List("P1", "P2", "P3")
val communities = List("C1", "C2", "C3", "C4")
case class Combination(food: String, place: String, community: String)
def allCombinations() =
for {
food <- foods; place <- places; community <- communities
} yield {
val comb = Combination(food, place, community)
println(comb)
comb
}
//Prints all items
val combinations = allCombinations()
def allCombinationsView() =
for {
//Use a view of each list
food <- foods.view; place <- places.view; community <- communities.view
} yield {
val comb = Combination(food, place, community)
println(comb)
comb
}
//Prints nothing
val combinationsView = allCombinationsView()
//Prints 5 items
val five = combinationsView.take(5).toList
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With