2015-08-21 13 views
7

Ich mag wie im Code eine Kombination aus einigen Werten erzeugen unter:Idiomatic Scala Art und Weise der Erzeugung von Kombinationen lazily

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 
    } 

} 

jedoch das Problem mit diesem Ansatz ist, dass alle Daten auf einmal erzeugt werden. Dies ist ein großes Problem, wenn die Größe von foods, places und communities sehr groß wird. Es könnte auch andere Parameter als diese drei geben.

Also ich möchte in der Lage sein, Kombinationen in einer Fortsetzung Stil, so dass eine Kombination nur generiert wird, wenn es angefordert wird.

Was wäre eine idiomatische Scala?

Antwort

4

Sie können dies tun, indem Sie eine View über jede Liste verwenden. Im folgenden Code habe ich einen Nebeneffekt hinzugefügt, so dass es sichtbar ist, wenn das yield für jedes Element aufgerufen wird.

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 
7

Sie verwenden 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 alle Daten. Wenn Sie nur einmal iterieren möchten, verwenden Sie stattdessen Iterator, was bereits durchgelaufene Elemente zur Müllsammlung bringen soll.

Verwandte Themen