文档章节

内建控制结构之for表达式

柳哥
 柳哥
发布于 2014/06/07 12:33
字数 1569
阅读 71
收藏 1
点赞 0
评论 0

Scala的for表达式是枚举操作的“瑞士军刀”,它可以让你用不同的方式把若干简单的成分组合起来以表达各种各样的枚举。


枚举集合类
For能做的最简单的事情就是把集合中所有元素都枚举一遍。如例:

package scalaTest
object Test4 {
    def main(args:Array[String]) {
        val fileHere = (new java.io.File(".")).listFiles
        for(file <- fileHere) println(file)
    }
}

通过使用被称为发生器的语法“file <- filesHere”,我们遍历了filesHere的元素。每一次枚举,名为file的新的val就被元素值初始化。编译器能够推断出file的类型是File,因为fileHere是Array[File]。对于每一次枚举,for表达式的函数体println(file),将被执行一次。由于File的toString方法生成文件或目录的名称,因此当前目录的所有文件和目录的名称都会被打印出来。
For表达式语法对任何种类的集合类都有效,而不只是数组。如例,你可以使用类似“1 to 5”这样的语法很方便地创建Range(这个后面再讲解),然后用for做枚举。

package scalaTest
object Test4 {
    def main(args:Array[String]) {
        for(i <- 1 to 9) println("Iteration " + i)
    }
}

如果不想包括被枚举的Range上边界,还可以用until替代to,如例:

package scalaTest
object Test4 {
    def main(args:Array[String]) {
        for(i <- 1 until 9) println("Iteration " + i)     //注意这里
    }
}


过滤
有时候你并不想枚举集合的全部元素,而只是想过滤出某个子集。这可以通过在for表达式的括号中添加过滤器(if子句)实现。如例:

package scalaTest
object Test4 {
    def main(args:Array[String]) {
        for(i <- 1 until 9 if i % 2 == 0) println("Iteration " + i)
    }
}

或者也可以采用如下写法:

package scalaTest
object Test4 {
    def main(args:Array[String]) {
        for(i <- 1 until 9)
            if(i % 2 == 0) println("Iteration " + i)
    }
}

这段代码对于指令式背景的程序员来说看上去更熟悉一些。然而指令式的格式只是可选的实现方法之一。For表达式之所以被称为“表达式”是因为它能产生有意义的值,其类型取决于for表达式<-子句的集合。需要的话,你可以包含更多的过滤器。只要不断添加if子句即可。如例:

package scalaTest
object Test4 {
    def main(args:Array[String]){
        for(
            i <- 1 until 9
            if i % 2 == 0;    //注意这里要分号
            if i % 4 == 0
        ) println("Iteration " + i)
    }
}

注意:如果在发生器中加入超过一个过滤器,if子句必须用分号分隔注:在scala2.10.7版本下好像不用分号了!!!)。


嵌套枚举
如果加入多个 <-子句,你就得到了嵌套的“循环”。如下例:

package scalaTest
object Test4 {
    def main(args:Array[String]){
        val arr = Array(Array(1,2,3,4,5),Array(11,12,13,14,15))
        for(
            ar <- arr
            if ar(0) > 10;    //注意这里要加分号
            a <- ar
            if a % 2 == 0 
        )println("Iteration " + a)
    }
}

注意嵌套枚举之间也必须用分号分隔。如果愿意的话,你可以使用花括号代替小括号包裹发生器和过滤器你用花括号的好处是可以省略使用小括号时必须加的分号(当然不去掉分号也是可以的);如例:

package scalaTest
object Test4 {
    def main(args:Array[String]){
        val arr = Array(Array(1,2,3,4,5),Array(11,12,13,14,15))
        for{        //注意这里,是大括号哦
            ar <- arr if ar(0) > 10
            a <- ar if a % 2 == 0
        }println("Iteration " + a)
    }
}


流间变量绑定

package scalaTest
object Test4 {
    def main(args:Array[String]){
        val arr = Array(Array("  a","b"," c "),Array("D","  E","F   "))
        for{
            ar <- arr if ar(0).trim == "a"
            a <- ar if a.trim == "c"
        }println(a.trim)
    }
}

请注意前面的代码段中重复出现了表达式a.trim,这是个不可忽略的计算,因此你或许希望只算一遍。这可以通过用等号(=)把结果绑定到新变量实现。绑定的变量被当作val引入和使用,不过不带关键字val,如例:

package scalaTest
object Test4{
    def main(args:Array[String]){
        val arr = Array(Array("a","b  ","  c  "),Array("D","  E","F   "))
        for{
            ar <- arr if ar(0).trim == "a"
            a <- ar            //注意,这里要么换行,要么加分号
            k = a.trim if k == "c"
        }println(k)
    }
}

不换行,加分号的例子:

package scalaTest
object Test4 {
    def main(args:Array[String]) {
        val arr = Array(Array(" a","b "," c "),Array("D","  E","F  "))
        for{
            ar <- arr if ar(0).trim == "a"
            a <- ar;k = a.trim if k == "c"    //这里加了分号
        }println(k)
    }
}

代码中,名为k的变量被从半路引入for表达式,并被初始化为a.trim的结果值。于是之后的for表达式在两个地方使用了新的变量,一次在if中,另一次在println中。


制造新集合
到现在为止所有的例子都只是对枚举值进行操作然后就释放,除此之外,你还可以创建一个值去记住每一次的迭代只要在for表达式之后加上关键字yield。如例:

package scalaTest
object Test4 {
    def main(args:Array[String]){
        val arr = Array(Array(" a","b "," c "),Array("D","  E","F  "))
        //注意这里
        var arr2 = for{
            ar <- arr if ar(0).trim == "a"
            a <- ar;k = a.trim if k == "c" || k == "b"
        }yield k
        for(s <- arr2) println("子集合元素: " + s)
    }
}

又例:

package scalaTest
object Test4{
    def main(args:Array[String]){
        val arr = Array(Array(" a","b "," c "),Array("D","  E","F  "))
        def fuOne(arr:Array[Array[String]]) = for{
            ar <- arr if ar(0).trim == "a"
            a <- ar;k = a.trim if k== "c" || k == "b"
        }yield k
        for(s <- funOne(arr)) println("子集合元素: " + s)
    }
}

For表达式在每次执行的时候都会产生一个新值,本例中是k。当for表达式完成的时候,结果将是包含了所有产生值的集合对象。对象的类型基于枚举子句处理的集合类型(上例中就是Array[String],这里是一维的)。
另外,请注意放置yield关键字的地方。对于for-yield表达式的语法是这样的 :for {子句} yield {循环体},如例:

package scalaTest
object Test4 {
    def main(args:Array[String]){
        val arr = Array(Array(" a","b "," c "),Array("D","  E","F  "))
        def funOne(arr:Array[Array[String]]) = for{
            ar <- arr if ar(0).trim == "a"
            a <- ar;k = a.trim if k == "c" || k == "b"
        }yield{
            println("~~~~~" + k)
            k
        }
    }
}

yield在整个循环体之后。即使循环体是被花括号包围的代码块,也一定要把yield放在左花括号之后
截止目前,你已经看过了scalafor表达式的所有主要特征,不过这一段过得实在是快了一些,我们后面会再详细介绍。

© 著作权归作者所有

共有 人打赏支持
柳哥
粉丝 202
博文 394
码字总数 347782
作品 0
杭州
技术主管
内建控制结构之if表达式

Scala的if语句与其它语言相比没有什么不同。它可以检测条件并根据其是否为真,执行两个分支中的一个。下面是常见的以指令式风格编写的例子: package scalaTestobject Test4 { def main(arg...

柳哥 ⋅ 2014/06/07 ⋅ 0

freemarker语法介绍及其入门

FreeMarker标签使用 一、FreeMarker模板文件主要有4个部分组成 1、文本,直接输出的部分 2、注释,即<#--...-->格式不会输出 3、插值(Interpolation):即${..}或者#{..}格式的部分,将使用数...

wersdffg ⋅ 2014/09/30 ⋅ 0

freemarker总结

Freemarker 使用总结 FreeMarker模板文件主要由如下4个部分组成: 文本:直接输出部分 注释:<!-- …-->格式部分,不输出 插值:即${}或者#{}部分,使用数据模型中的部分替代输出. FTL指令:freema...

忘川-hsm ⋅ 2016/11/01 ⋅ 0

FreeMarker标签介绍及各种数据类型处理

FreeMarker标签使用 一、FreeMarker模板文件主要有4个部分组成 1、文本,直接输出的部分 2、注释,即<#--...-->格式不会输出 3、插值(Interpolation):即${..}或者#{..}格式的部分,将使用数...

驛路梨花醉美 ⋅ 2016/11/29 ⋅ 0

FreeMarker标签使用

一、FreeMarker模板文件主要有4个部分组成 1、文本,直接输出的部分 2、注释,即<#--...-->格式不会输出 3、插值(Interpolation):即${..}或者#{..}格式的部分,将使用数据模型中的部分替代...

罪恶的花生 ⋅ 2012/05/31 ⋅ 0

看书 Python 源码分析笔记 (五)

第9章 Python 虚拟机中的一般表达式 这里一般表达式指对象创建语句, 打印语句等. if, while 等归为控制流语句于下一章. 简单内建对象的创建 示例 python 代码: i = 1 // int objects = "Pyt...

刘军兴 ⋅ 2015/12/21 ⋅ 0

FreeMarker标签介绍

FreeMarker标签使用 一、FreeMarker模板文件主要有4个部分组成 1、文本,直接输出的部分 2、注释,即<#--...-->格式不会输出 3、插值(Interpolation):即${..}或者#{..}格式的部分,将使用数...

机器学习 ⋅ 2013/04/24 ⋅ 0

内建控制结构之while循环

Scala的while循环与其他语言一致。包括状态判断和循环体,只要状态保持真,循环体就一遍遍被执行,如: package scalaobject ScalaTest { def main(args:Array[String]):Unit = { var a = 1 ...

柳哥 ⋅ 2014/06/07 ⋅ 0

《深入理解ES6》笔记—— JavaScript中的类class(9)

ES5中的近类结构 ES5以及之前的版本,没有类的概念,但是聪明的JavaScript开发者,为了实现面向对象,创建了特殊的近类结构。 ES5中创建类的方法:新建一个构造函数,定义一个方法并且赋值给...

zdhsoft ⋅ 2017/07/31 ⋅ 0

HiveQL 初级实战

2009-09-22 @ taobao 引言 Hive Shell 进入shell 退出shell 查看已有表 查看表结构 执行查询 数据类型 内建操作符和函数 操作符 函数 引言 本文的主要目的是让读者可以使用hiveQL对已有的海量...

zhongl ⋅ 2011/09/23 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

windows profesional 2017 build problem

.net framework .... https://stackoverflow.com/questions/43330915/could-not-load-file-or-assembly-microsoft-build-frameworkvs-2017...

机油战士 ⋅ 42分钟前 ⋅ 0

python3中报错的解决方法(长期更新)

1、ImportError: No module named ‘DjangoUeditor’ 出错原因:安装DjangoUeditor库适用于python2,需要下载适用python3的 下载地址:https://github.com/twz915/DjangoUeditor3 2、python3......

xiaoge2016 ⋅ 46分钟前 ⋅ 0

数据结构与算法之双向链表

一、双向链表 1.双向链表的结点结构 typedef struct DualNode{ ElemType data; struct DualNode *prior; // 前驱结点 struct DualNode *next; // 后继结点}DualNode, *DuL...

aibinxiao ⋅ 今天 ⋅ 0

五大最核心的大数据技术

大数据技术有5个核心部分,数据采集、数据存储、数据清洗、数据挖掘、数据可视化。关于这5个部分,有哪些核心技术?这些技术有哪些潜在价值?看完今天的文章就知道了。 大数据学习群:7165810...

董黎明 ⋅ 今天 ⋅ 0

PhpStorm 头部注释、类注释和函数注释的设置

首先,PhpStorm中文件、类、函数等注释的设置在:setting-》Editor-》FIle and Code Template-》Includes下设置即可,其中方法的默认是这样的: /**${PARAM_DOC}#if (${TYPE_HINT} != "v...

nsns ⋅ 今天 ⋅ 0

spring.net AOP

http://www.springframework.net/doc-latest/reference/html/aop-quickstart.html https://www.cnblogs.com/wujy/archive/2013/04/06/3003120.html...

whoisliang ⋅ 今天 ⋅ 0

【HAVENT原创】创建 Dockerfile 生成新的镜像,并发布到 DockerHub

注意:Win7 与 Win10 的版本存在差异,Win7 版本使用 Docker Quickstart Terminal 进入控制台,Win10下面直接用管理员权限打开控制台或者 PowerShell 即可;另外 Win7 下面只能访问 C盘,/ap...

HAVENT ⋅ 今天 ⋅ 0

pom.xml出现web.xml is missing ...解决方案

提示信息应该能看懂。也就是缺少了web.xml文件,<failOnMissingWebXml>被设置成true了。 搜索了一下,Stack Overflow上的答案解决了问题,分享一下。 目前被顶次数最多的回答原文如下: This...

源哥L ⋅ 今天 ⋅ 0

js时间戳与日期格式之间相互转换

1. 将时间戳转换成日期格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 简单的一句代码 var date = new Date(时间戳); //获取一个时间对象 /** 1. 下面是获取时间日期的方法,需要什么样的格式自己...

Jack088 ⋅ 今天 ⋅ 0

web添加log4j

添加xml配置log4j.properties # Global logging configuration---root日志设置#log4j.rootLogger=info,dailyRollingFile,stdoutlog4j.rootLogger=debug,stdout,dailyRollingFile---......

黄柳淞 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部