2015-08-21 12 views
7

voglio generare una combinazione di alcuni valori, come nel seguente codice:Idiomatic Scala modo di combinazioni che generano pigramente

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 
    } 

} 

Tuttavia, il problema di questo approccio è che, tutti i dati vengono generati in una sola volta. Questo è un grosso problema quando la dimensione di foods, places e communities diventa molto grande. Inoltre potrebbero esserci altri parametri oltre a questi tre.

Quindi voglio essere in grado di generare combinazioni, in uno stile di continuazione, tale che una combinazione venga generata solo quando viene richiesta.

Quale sarebbe un modo idiomatico di farlo in Scala?

risposta

4

È possibile eseguire questa operazione utilizzando un View su ogni elenco. Nel codice qui sotto ho aggiunto un effetto collaterale, quindi è visibile quando viene chiamato il numero yield per ciascun elemento.

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

si utilizza flussi:

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 
    } 

} 

Un Stream cache tutti i dati. Se si desidera solo iterare una volta, utilizzare invece Iterator, che dovrebbe raccogliere elementi già attraversati.

Problemi correlati