使用for和yield生成的集合类型

22

在Scala中,当我评估一个for循环时,我会得到一个不可变的IndexedSeq(具有类似数组的性能特征,如高效的随机访问):

scala> val s = for (i <- 0 to 9) yield math.random + i
s: scala.collection.immutable.IndexedSeq[Double] = Vector(0.6127056766832756, 1.7137598183155291, ...

for循环中带有yield,它总是返回IndexedSeq吗?还是它也可以返回其他类型的集合类(例如LinearSeq)?如果它可以返回其他类型,那么是什么决定了返回类型,如何影响它?

我正在使用Scala 2.8.0.RC3。


3
请看这两个链接:https://dev59.com/xnNA5IYBdhLWcg3wNa6T#1059501 和 https://dev59.com/e3I-5IYBdhLWcg3wsKv9。 - michael.kebe
2个回答

19

感谢michael.kebe的评论。

这篇文章解释了如何将for转换为使用mapflatMapfilterforeach操作。所以我的例子:

val s = for (i <- 0 to 9) yield math.random + i

被翻译成类似以下的代码(我不确定在这种情况下是否被翻译成map还是flatMap):

val s = (0 to 9) map { math.random + _ }

对于类似于集合上的map操作,其结果类型取决于你调用它的集合类型。 0 到 9 的类型是 Range.Inclusive

scala> val d = 0 to 9
d: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

对此进行map操作的结果是一个IndexedSeq(因为集合库内部有构建器)。

那么,回答我的问题:使用for (...) yield ...得到的结果取决于括号内的类型。如果我想要一个List作为结果,可以这样做:

scala> val s = for (i <- List.range(0, 9)) yield math.random + i
s: List[Double] = List(0.05778968639862214, 1.6758775042995566, ...

2
在您的情况下,它被翻译为map。如果您有一个带有两个生成器的for推导式,则将其转换为flatMap/map组合。因此,对于(i <- 0 until 9; j <- 0 until i)yield(i*j)被翻译为(0 until 9)。flatMap { case i =>(0 until i)。map { case j => i * j }}。 - Arjan Blokzijl
取决于括号内的类型,更精确地说,是第一个右侧参数确定了类型。 - Th 00 mÄ s

6

您可以始终使用 toList 将范围转换为列表:

> val s = for (i <- (0 to 9).toList) yield math.random + i
> s  : List[Double]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接