W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Scala 中的 for 表達(dá)式有如一把完成迭代任務(wù)的瑞士軍刀,它允許你使用一些簡(jiǎn)單的部件以不同的方法組合可以完成許多復(fù)雜的迭代任務(wù)。簡(jiǎn)單的應(yīng)用比如枚舉一個(gè)整數(shù)列表,較復(fù)雜的應(yīng)用可以同時(shí)枚舉多個(gè)不同類型的列表,根據(jù)條件過濾元素,并可以生成新的集合。
這是使用 for 表示式的一個(gè)基本用法,和 Java 的 for 非常類似,比如下面的代碼可以枚舉當(dāng)前目錄下所有文件:
val filesHere = (new java.io.File(".")).listFiles
for( file <-filesHere)
println(file)
其中如 file < – filesHere 的語(yǔ)法結(jié)構(gòu),在 Scala 中稱為“生成器 (generator)”。 本例中 filesHere 的類型為 Array[File],每次迭代 變量 file 會(huì)初始化為該數(shù)組中一個(gè)元素, File 的 toString()為文件的文件名,因此 println(file)打印出文件名。 Scala 的 for 表達(dá)式支持所有類型的集合類型,而不僅僅是數(shù)組,比如下面使用 for 表達(dá)式來枚舉一個(gè) Range 類型。
scala> for ( i<- 1 to 5 ){ println ("Interation " + i)}
Interation 1
Interation 2
Interation 3
Interation 4
某些時(shí)候,你不想枚舉集合中的每個(gè)元素,而是只迭代某些符合條件的元素,在 Scala 中,你可以為 for 表達(dá)式添加一個(gè)過濾器–在 for 的括號(hào)內(nèi)添加一個(gè) if 語(yǔ)句,例如:修改前面枚舉文件的例子,改成只列出 .scala 文件如下:
val filesHere = (new java.io.File(".")).listFiles
for( file println(file)
如果有必要的話,你可以使用多個(gè)過濾器,只要添加多個(gè) if 語(yǔ)句即可,比如,為保證前面列出的文件不是目錄,可以添加一個(gè) if,如下面代碼:
val filesHere = (new java.io.File(".")).listFiles
for( file <-filesHere
if file.isFile
if file.getName.endsWith(".scala")
) println(file)
fo r表達(dá)式支持多重迭代,下面的例子使用兩重迭代,外面的循環(huán)枚舉 filesHere,而內(nèi)部循環(huán)枚舉該文件的每一行文字。實(shí)現(xiàn)了類似 Unix grep 命令:
val filesHere = (new java.io.File(".")).listFiles
def fileLines (file : java.io.File) =
scala.io.Source.fromFile(file).getLines().toList
def grep (pattern: String) =
for (
file if file.getName.endsWith(".scala");
line <-fileLines(file)
if line.trim.matches(pattern)
) println(file + ":" + line.trim)
grep (".*gcd.*")
注意上面代碼中兩個(gè)迭代之間使用了”;”,如果你使用{} 替代 for 的()的括號(hào),你可以不使用“;”分隔這兩個(gè)“生成器”,這是因?yàn)?Scala 編譯器不推算包含在括號(hào)內(nèi)的省掉的“;”。使用{}改寫的代碼如下:
val filesHere = (new java.io.File(".")).listFiles
def fileLines (file : java.io.File) =
scala.io.Source.fromFile(file).getLines().toList
def grep (pattern: String) =
for {
file if file.getName.endsWith(".scala")
line <-fileLines(file)
if line.trim.matches(pattern)
} println(file + ":" + line.trim)
grep (".*gcd.*")
這兩段代碼是等效的。
你可以注意到前面代碼使用了多次 line.trim,如果 trim 是個(gè)耗時(shí)的操作,你可以希望 trim 只計(jì)算一次,Scala 允許你使用=號(hào)來綁定計(jì)算結(jié)果到一個(gè)新變量。綁定的作用和 val 類似,只是不需要使用 val 關(guān)鍵字,例如,修改前面的例子,只計(jì)算一次 trim,把結(jié)果保存在 trimmed 變量中。
val filesHere = (new java.io.File(".")).listFiles
def fileLines (file : java.io.File) =
scala.io.Source.fromFile(file).getLines().toList
def grep (pattern: String) =
for {
file if file.getName.endsWith(".scala")
line <-fileLines(file)
trimmed=line.trim
if trimmed.matches(pattern)
} println(file + ":" + trimmed)
grep (".*gcd.*")
for 表達(dá)式也可以用來生產(chǎn)新的集合,這是 Scala 的 for 表達(dá)式比 Java 的 for 語(yǔ)句功能強(qiáng)大的地方。它的基本語(yǔ)法如下:
for clauses yield body
關(guān)鍵字 yield 放在 body 的前面,for 沒迭代一次,產(chǎn)生一個(gè) body,yield 收集所有的 body 結(jié)果,返回一個(gè) body 類型的集合。比如,前面列出所有 .scala 文件,返回這些文件的集合:
def scalaFiles =
for {
file if file.getName.endsWith(".scala")
} yield file
scalaFiles 的類型為 Array[File]。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: