Scala 提供了一种轻量级符号来表示序列理解。理解具有以下形式 for (enumerators) yield e
,其中 enumerators
指的是枚举器列表。枚举器 要么是生成器,要么是保护(参见:控制结构)。理解会为枚举器生成的每个绑定计算主体 e
,并返回这些值的一个序列。
这是一个示例
case class User(name: String, age: Int)
val userBase = List(
User("Travis", 28),
User("Kelly", 33),
User("Jennifer", 44),
User("Dennis", 23))
val twentySomethings =
for (user <- userBase if user.age >=20 && user.age < 30)
yield user.name // i.e. add this to a list
twentySomethings.foreach(println) // prints Travis Dennis
case class User(name: String, age: Int)
val userBase = List(
User("Travis", 28),
User("Kelly", 33),
User("Jennifer", 44),
User("Dennis", 23))
val twentySomethings =
for user <- userBase if user.age >=20 && user.age < 30
yield user.name // i.e. add this to a list
twentySomethings.foreach(println) // prints Travis Dennis
带有 yield
语句的 for
循环会返回一个结果,其容器类型由第一个生成器决定。 user <- userBase
是一个 List
,并且因为我们说 yield user.name
,其中 user.name
是一个 String
,所以总体结果是一个 List[String]
。而 if user.age >=20 && user.age < 30
是一个保护,它会过滤掉不在二十多岁的人员。
这里是一个使用两个生成器的更复杂的示例。它计算 0
和 n-1
之间所有数字对,其和等于给定值 v
def foo(n: Int, v: Int) =
for (i <- 0 until n;
j <- 0 until n if i + j == v)
yield (i, j)
foo(10, 10).foreach {
case (i, j) =>
println(s"($i, $j) ") // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5) (6, 4) (7, 3) (8, 2) (9, 1)
}
def foo(n: Int, v: Int) =
for i <- 0 until n
j <- 0 until n if i + j == v
yield (i, j)
foo(10, 10).foreach {
(i, j) => println(s"($i, $j) ") // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5) (6, 4) (7, 3) (8, 2) (9, 1)
}
这里 n == 10
,v == 10
。在第一次迭代中,i == 0
,j == 0
,所以 i + j != v
,因此不会生成任何内容。在 i
增加到 1
之前,j
会增加 9 次。如果没有 if
保护,这只会打印以下内容
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 0) ...
请注意,推导式并不局限于列表。支持操作 withFilter
、map
和 flatMap
(具有适当类型)的每种数据类型都可以在序列推导式中使用。
你可以在推导式中省略 yield
。在这种情况下,推导式将返回 Unit
。如果你需要执行副作用,这会很有用。下面是一个与前一个等效的程序,但没有使用 yield
def foo(n: Int, v: Int) =
for (i <- 0 until n;
j <- 0 until n if i + j == v)
println(s"($i, $j)")
foo(10, 10)
def foo(n: Int, v: Int) =
for i <- 0 until n
j <- 0 until n if i + j == v
do println(s"($i, $j)")
foo(10, 10)
更多资源
- Scala 书籍 中“For 推导式”的其他示例