懒惰地生成组合的惯用 Scala 方式
Idiomatic Scala way of generating combinations 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
}
}
然而,这种方法的问题在于,所有数据都是一次性生成的。当 foods
、places
和 communities
的大小变得非常大时,这是一个大问题。除了这三个参数之外,还可以有其他参数。
所以我希望能够以连续的方式生成组合,以便仅在请求时生成组合。
Scala 的惯用方式是什么?
您使用流:
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
}
}
一个Stream
缓存了所有的数据。如果您只想迭代一次,请改用 Iterator
,它应该垃圾收集已经遍历的元素。
您可以通过在每个列表上使用 View
来完成此操作。在下面的代码中,我添加了一个副作用,因此当为每个元素调用 yield
时它是可见的。
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
我想生成一些值的组合,如下面的代码所示:
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
}
}
然而,这种方法的问题在于,所有数据都是一次性生成的。当 foods
、places
和 communities
的大小变得非常大时,这是一个大问题。除了这三个参数之外,还可以有其他参数。
所以我希望能够以连续的方式生成组合,以便仅在请求时生成组合。
Scala 的惯用方式是什么?
您使用流:
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
}
}
一个Stream
缓存了所有的数据。如果您只想迭代一次,请改用 Iterator
,它应该垃圾收集已经遍历的元素。
您可以通过在每个列表上使用 View
来完成此操作。在下面的代码中,我添加了一个副作用,因此当为每个元素调用 yield
时它是可见的。
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