2014-07-01 15 views
0

Here我们了解,像一个表达式:在Scala中,yield如何扩展到多维循环?

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]]

我该如何做到这一点?

感谢您的回答(:

回答

5

它在相关doc很好的解释,特别是:

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

将被翻译成

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

我不认为有一种抽象任意嵌套理解的方法(除非你使用巫术魔法,如宏)

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是arbitraray序列或单子也是可能的。请参阅this gist获取必要的代码。

+0

我明白'Vector'是'Indexseq'的子类型,但为什么不在这里使用'Indexseq'? –

+0

感谢您的回答,但'upto50'的输出并不按需要增量。是否可以对其进行修改,使其产生“严格递增顺序”?再一次,谢谢你的回答(: –

+0

糟糕,我错过了每个循环都从前一个循环的值开始,你说得对,'IndexedSeq'更有意义。 – wingedsubmariner