【问题标题】:Idiomatic Scala way of generating combinations lazily懒惰地生成组合的惯用 Scala 方式
【发布时间】:2015-08-21 07:22:17
【问题描述】:

我想生成一些值的组合,如下面的代码:

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
  }

}

但是,这种方法的问题在于,所有数据都是一次生成的。当foodsplacescommunities 的大小变得非常大时,这是一个大问题。除了这三个之外,还可能有其他参数。

所以我希望能够以延续样式生成组合,以便仅在请求时生成组合。

Scala 的惯用方式是什么?

【问题讨论】:

    标签: scala combinations


    【解决方案1】:

    您使用流:

    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,它应该垃圾收集已经遍历的元素。

    【讨论】:

      【解决方案2】:

      您可以通过在每个列表上使用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
      

      【讨论】:

        猜你喜欢
        • 2019-06-20
        • 2011-12-31
        • 2010-09-26
        • 1970-01-01
        • 2012-11-04
        • 1970-01-01
        • 2019-04-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多