如何在Scala中的多维循环中扩展到yield?

时间:2014-07-01 12:39:59

标签: scala

Here我们知道一个表达式:

for( i <- 1 to 10 ) yield i + 1

将扩展为

( 1 to 10 ).map( _+1 )

但是下面的表达式扩展到了什么?

for( i <- 1 to 50  j <- i to 50 ) yield List(1,i,j)

这是对的吗?

( 1 to 50 ).map( x => (1 to 50 ).map(List(1,x,_))

我对这个问题感兴趣,因为我想创建一个执行多个Xi <- Xi-1 to 50操作的函数,如下所示:

for( X1 <- 1 to 50  X2 <- X1 to 50  X3 <- X2 to 50 ..... Xn <- Xn-1 to 50 ) 
    yield List(1,X1,X2,X3,.....,Xn)

该函数有一个参数:dimension表示上述表达式中的n 其返回类型为IndexSeq[List[Int]]

我怎样才能做到这一点?

感谢您的回答(:

2 个答案:

答案 0 :(得分:5)

在相关的doc中对此进行了很好的解释。特别是:

for(x <- c1; y <- c2; z <- c3) yield {...}

将被翻译成

c1.flatMap(x => c2.flatMap(y => c3.map(z => {...})))

我不认为有一种方法可以抽象出任意嵌套理解(除非你使用巫毒魔法,就像宏一样)

答案 1 :(得分:0)

有关for循环扩展到的内容的解释,请参阅om-nom-nom的答案。我想回答开场问题的第二部分,如何实现可以执行的功能:

for( X1 <- 1 to 50  X2 <- X1 to 50  X3 <- X2 to 50 ..... Xn <- Xn to 50 ) 
    yield List(1,X1,X2,X3,.....,Xn)

您可以使用:

def upto50(dimension: Int) = {
  def loop(n: Int, start: Int): IndexedSeq[List[Int]] = {
    if (n > dimension)
      IndexedSeq(List())
    else {
      (n to 50).flatMap(x => loop(n + 1, x).map(x :: _))
    }
  }
  loop(1, 1)
}

我们递归地计算每个循环,从内到外工作,从Xn to 50开始并构建解决方案。

更常见案例的解决方案:

for( X1 <- S1  X2 <- S2  X3 <- S3 ..... Xn <- Sn ) 
    yield List(1,X1,X2,X3,.....,Xn)

其中S1..Sn是任意序列或monad也是可能的。请参阅this gist以获取必要的代码墙。