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 Book 中「For 推導式」的其他範例