第十章 Scala 容器基础(十三):使用for yield转化集合
2016-04-12 00:00
295 查看
摘要: 使用for/yield可以根据你的需求把一个集合转化为另一个新的集合,新老集合的类型不变
使用for/yield创建一个集合的拷贝:
你可以创建一个新的集合,通过对原有集合的每个元素翻倍,也可以把原集合的元素变为1/2
把一组字符串转化为大写:
你的算法可以返回任何你想要的集合,下面我们来把一个集合转化为2元组:
下面这个算法,返回原集合元素与元素长度组成的二元祖:
定义一个case class Person,然后根据一组姓名来创建Person集合:
你可以在for/yield语句中添加if来对原有集合元素进行过滤:
通常情况下,原集合类型决定了for/yield返回新集合的类型。如果你使用一个ArrayBuffer作为原集合,那么新集合肯定也是ArrayBuffer:
一个List返回一个List:
Using guards
当你给for添加一个grards(警卫),并且想把代码写成多行表达式,推荐的编码风格是使用花括号而不是圆括号:
这样代码更具可读性,尤其是当你给for添加多个grards(警卫)的时候。
当我第一次开始使用Scal的时候a,我总是使用for/yield表达式来做这样的集合转换工作,但是有一个我发现我可以使用更简便的方式达到同样的目标,那就是map方法。下一节,我们就来介绍如何使用map方法来吧一个集合转化为另一个集合。
Problem
你想要对一个原有集合的元素通过某种算法进行处理,然后生成一个新的集合。Solution
使用for/yield结构外加你的算法就可以从一个原有集合创建一个新的集合。首先我们要有一个集合scala> val a = Array(1, 2, 3, 4, 5) a: Array[Int] = Array(1, 2, 3, 4, 5)
使用for/yield创建一个集合的拷贝:
scala> for(e <- a) yield e res12: Array[Int] = Array(1, 2, 3, 4, 5)
你可以创建一个新的集合,通过对原有集合的每个元素翻倍,也可以把原集合的元素变为1/2
scala> for(e <- a) yield e * 2 res14: Array[Int] = Array(2, 4, 6, 8, 10) scala> for(e <- a) yield e / 2 res16: Array[Int] = Array(0, 1, 1, 2, 2)
把一组字符串转化为大写:
scala> for(fruit <- fruits) yield fruit.toUpperCase res17: scala.collection.immutable.Vector[String] = Vector(APPLE, BANANA, LIME, ORANGE)
你的算法可以返回任何你想要的集合,下面我们来把一个集合转化为2元组:
scala> for (i <- 0 until fruits.length) yield (i, fruits(i)) res18: scala.collection.immutable.IndexedSeq[(Int, String)] = Vector((0,apple), (1,banana), (2,lime), (3,orange))
下面这个算法,返回原集合元素与元素长度组成的二元祖:
scala> for(fruit <- fruits) yield (fruit, fruit.length) res20: scala.collection.immutable.Vector[(String, Int)] = Vector((apple,5), (banana,6), (lime,4), (orange,6))
定义一个case class Person,然后根据一组姓名来创建Person集合:
scala> case class Person (name: String) defined class Person scala> val friends = Vector("Mark", "Regina", "Matt") friends: scala.collection.immutable.Vector[String] = Vector(Mark, Regina, Matt) scala> for (f <- friends) yield Person(f) res21: scala.collection.immutable.Vector[Person] = Vector(Person(Mark), Person(Regina), Person(Matt))
你可以在for/yield语句中添加if来对原有集合元素进行过滤:
scala> val x = for (e <- fruits if e.length < 6) yield e.toUpperCase x: scala.collection.immutable.Vector[String] = Vector(APPLE, LIME)
Discussion
for循环和yield的结合可以看作是for表达式活着序列表达式。它从一个原有集合的基础上返回一个新的集合。如果你是第一个使用for/yield结构,它会让你想到有一个桶活着临时区域在里边。每一个来自原有集合的元素被转化然后执行yield操作,被加入到桶中。然后当循环结束的时候,桶中的所有元素被yield表达式返回。通常情况下,原集合类型决定了for/yield返回新集合的类型。如果你使用一个ArrayBuffer作为原集合,那么新集合肯定也是ArrayBuffer:
scala> val fruits = scala.collection.mutable.ArrayBuffer("apple", "banana") fruits: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(apple, banana) scala> val x = for (e <- fruits) yield e.toUpperCase x: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(APPLE, BANANA)
一个List返回一个List:
scala> val fruits = "apple" :: "banana" :: "orange" :: Nil fruits: List[String] = List(apple, banana, orange) scala> val x = for (e <- fruits) yield e.toUpperCase x: List[String] = List(APPLE, BANANA, ORANGE)
Using guards
当你给for添加一个grards(警卫),并且想把代码写成多行表达式,推荐的编码风格是使用花括号而不是圆括号:
scala> val fruits = Vector("apple", "banana", "lime", "orange") fruits: scala.collection.immutable.Vector[String] = Vector(apple, banana, lime, orange) scala> for { | e <- fruits | if e.length < 6 | } yield e.toUpperCase res25: scala.collection.immutable.Vector[String] = Vector(APPLE, LIME)
这样代码更具可读性,尤其是当你给for添加多个grards(警卫)的时候。
当我第一次开始使用Scal的时候a,我总是使用for/yield表达式来做这样的集合转换工作,但是有一个我发现我可以使用更简便的方式达到同样的目标,那就是map方法。下一节,我们就来介绍如何使用map方法来吧一个集合转化为另一个集合。
相关文章推荐
- Oracle Containers for J2EE远程安全漏洞(CVE-2014-0413)
- Windows下Scala环境搭建
- 杀毒软件 Dr.Web Anti-virus for Windows Vista 4.44.0 Beta
- C#中循环语句:while、for、foreach的使用
- for 提取文本整行内容的方法
- dos命令for用法详解
- for命令的一些bug分析
- 批处理 FOR参数/F之tokens详解
- Lua中数字for循环实例
- 杀毒软件 Dr.Web Anti-virus for Windows Vista 4.44.0 Beta
- Nero v3.0.0.0 for LINUX 版本 下载
- for语句中的几种分隔符形式小结
- Shell中的for和while循环详细总结
- C#中yield return用法分析
- 非常好的for 教程, 当时我就是看这个学习for 的第1/2页
- mysql Access denied for user ‘root’@’localhost’ (using password: YES)解决方法
- 批处理FOR 中的Delims和Tokens总结
- for 语句从入门到精通
- 最新的 for Vista RTM 驱动程序
- JavaScript中for循环的使用详解