微信扫一扫

028-83195727 , 15928970361
business@forhy.com

Scala之集合上常见的函数式风格的操作汇总

scala,filter,map,fold,reduce2016-11-24

目录


正文

函数式编程对集合操作有一些通行的“叫法”,或者更像是一些“俚语”,它们的含义清晰明确,但是很难顾名思义,比如常见的“filter”,”map”,”flatMap”,“redue”等等。本文会把一些主要“俚语”详细地解释一下,同时给出一些参考示例。

“过滤”相关的操作

filter

解释

设定一个判定结果为布尔型的过滤条件,应用到集合的每一个元素上,返回的是集合里所有满足条件的元素构成的一个子集。

示例

scala> List.range(1, 11).filter (_ % 3 == 0)
res1: List[Int] = List(3, 6, 9)
scala> List("the", "quick", "brown", "fox", "jumped","over", "the", "lazy", "dog").filter(_.length == 3)
res2: List[String] = List(the, fox, the, dog)

partition

解释

filter类型操作的一个变种,同样是设定一个判定结果为布尔型的过滤条件,应用到集合的每一个元素上,返回的是二个元素的Tuple, 第一个元素是所有满足条件的元素构成一个集合,第二个元素是所有不满足条件的元素构成一个集合。

示例

scala> List.range(1, 11).partition(_ % 3 == 0)
res3: (List[Int], List[Int]) = (List(3, 6, 9),List(1, 2, 4, 5, 7, 8, 10))

find

解释

filter类型操作的一个变种,同样是设定一个判定结果为布尔型的过滤条件,返回集合中满足条件的第一个元素。

示例

scala> List.range(1, 11).find(_ % 3 == 0)
res4: Option[Int] = Some(3)

takeWhile

解释

filter类型操作的一个变种,同样是设定一个判定结果为布尔型的过滤条件,从集合的第一个元素开始,逐一判定元素是否符合条件,在遇到第一个不符合条件的元素后随即结束过滤,返回的结果就是集合中前N个连续满足条件的元素。

示例

scala> List(1, 2, 3, -4, 5, 6, 7, 8, 9, 10) takeWhile (_ > 0)
res5: List[Int] = List(1, 2, 3)

“映射”相关的操作

map

解释

设定一个针对元素的“转换”操作,应用到集合的每一个元素上,返回的结果是每个元素被转换之后的新值组成的新集合。新的集合与旧集合大小一样,但元素都是更新的,甚至类型也会发生变化。

示例

scala> List(1, 2, 3, 4, 5) map (_ + 1)
res6: List[Int] = List(2, 3, 4, 5, 6)

scala> List("the", "quick", "brown", "fox", "jumped","over", "the", "lazy", "dog").map(_.length)
res7: List[Int] = List(3, 5, 5, 3, 6, 4, 3, 4, 3)

flatMap

解释

对于嵌套的集合(即集合中的元素还是集合),如果我们希望把每一个嵌套的子集“转换”成一个新的子集,这时候就应该使用flatMap。

示例

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_.toList)
res2: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_.reverse)
res3: List[Int] = List(3, 2, 1, 6, 5, 4, 9, 8, 7)

要特别注意的是flatMap使用的函数参数接收的是一个集合,返回的也是一个集合(GenTraversableOnce),你不能将一个集合元素“转换”成单一的值,比如,你不能这样做:

示例

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_ + 1)
<console>:12: error: type mismatch;
 found   : Int(1)
 required: String
       List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_ + 1)
                                                                      ^

如果你想针对嵌套集合中的每个元素进行装换得到一个统一的集合,你可以这做做:

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_.map(_+1))
res10: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10)

“扁平化”相关的操作

flatten

解释

在函数式编程里经常会出现嵌套的集合,我们需要频繁地把这种嵌套的结构”压“成”扁平“的单一集合,这个动作在函数式编程里叫”flatten”。即:将所有嵌套的集合的元素一一取出逐一放置到一个集合中。

示例

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)).flatten
res12: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> List("the", "quick", "brown", "fox", "jumped","over", "the", "lazy", "dog").flatten
res13: List[Char] = List(t, h, e, q, u, i, c, k, b, r, o, w, n, f, o, x, j, u, m, p, e, d, o, v, e, r, t, h, e, l, a, z, y, d, o, g)

“折叠”相关的操作

reduceLeft

解释

如果我们把集合看成是一张纸条,每一小段代表一个元素,那么reduceLeft就将这张纸条从左向右”折叠”,最前面的两个元素会首先“重叠”在一起,这时会使用传给reduceLeft的参数函数进行计算,返回的结果就像是已经折叠在一起的两段纸条,它们已经是一个叠加的状态了,所以它,也就是上次重叠的结果会继续做为一个单一的值和下一个元素继续“叠加”,直到折叠到集合的最后一个元素。

示例

scala> List.range(1, 10).reduceLeft(_+_)
res0: Int = 45

reduceRight

解释

同理,reduceRight就将这张纸条从右向左”折叠”。要留心reduceRight的地方时:它的操作方向是从右到左,但是参数的顺序却并不是,而是依然第一参数是左边的元素,第二参数是右边的元素。我们可以通过一个示例来验证:

示例

List.range(1, 10) reduceRight(_ - _)
// 8 - 9 = -1
// 7 - (-1) = 8
// 6 - 8 = -2
// 5 - (-2) = 7
// 4 - 7 = -3
// 3 - (-3) = 6
// 2 - 6 = -4
// 1 - (-4) = 5
// result: 5

foldLeft

解释

与reduceLeft极为相似,只是它开始操作的第一个元素是以参数的形式传入的,而不是集合的第一个元素。

示例

scala> List.range(1, 10).foldLeft(1)(_+_)
res1: Int = 46

foldRight

解释

与reduceRight极为相似,只是它开始操作的第一个元素是以参数的形式传入的,而不是集合的最后一个元素。

示例

scala> List.range(1, 10).foldRight(5)(_ - _)
res8: Int = 0

本文原文出处: http://blog.csdn.net/bluishglc/article/details/53320654 转载请注明出处。