Scala - 09 - 函数式编程:一些操作
发布时间:2020-12-16 09:02:43 所属栏目:安全 来源:网络整理
导读:1- 集合类( collection ) 系统地区分了可变的和不可变的集合。 scala.collection包中所有的集合类 可变集合(Mutable) 顾名思义,意味着可以修改,移除或者添加一个元素。 scala.collection.mutable 中的所有集合类: 不可变集合(Immutable) 对不可变集合的操
1- 集合类(collection)
系统地区分了可变的和不可变的集合。
scala.collection包中所有的集合类
可变集合(Mutable)
顾名思义,意味着可以修改,移除或者添加一个元素。
scala.collection.mutable 中的所有集合类:
不可变集合(Immutable)
scala.collection.immutable 中的所有集合类:
2- 列表(List)
List[T]val a = List(1,2,3,4) //> a : List[Int] = List(1,4) val b = 0 :: a //> b : List[Int] = List(0,1,4) val c = "x" :: "y" :: "z" :: Nil //> c : List[String] = List(x,y,z) val r0 = "z" :: Nil //> r0 : List[String] = List(z) val r1 = "y" :: r0 //> r1 : List[String] = List(y,z) val r2 = "x" :: r1 //> r2 : List[String] = List(x,z) val d = a ::: c //> d : List[Any] = List(1,4,x,z) d.head //> res0: Any = 1 d.tail //> res1: List[Any] = List(2,z) d.isEmpty //> res2: Boolean = false Nil.isEmpty //> res3: Boolean = true def test(tlist: List[Int]): String = { if (tlist.isEmpty) "" else tlist.head.toString + " " + test(tlist.tail) } //> test: (tlist: List[Int])String test(a) //> res4: String = "1 2 3 4 " ? val test = List(1,5) //> test : List[Int] = List(1,5) test.filter(x => x % 2 == 1) //> res0: List[Int] = List(1,5) "Double in 2018!".toList //> res1: List[Char] = List(D,o,u,b,l,e,i,n,8,!) "Double in 2018!".toList.filter(x => Character.isDigit(x)) //> res2: List[Char] = List(2,8) "Double in 2018!".toList.takeWhile(x => x != ‘i‘) //> res3: List[Char] = List(D,) 列表的遍历
可以使用for循环或foreach进行遍历
val list = List(1,3) //> list : List[Int] = List(1,3) for (elem <- list) println(elem) //> 1 //| 2 //| 3 list.foreach(elem => print(elem)) //> 123 list.foreach(print) //> 123 3- 映射(Map)
键值对的集合val test = Map(1 -> "Anliven",9 -> "Angel") //> test : scala.collection.immutable.Map[Int,String] = Map(1 -> Anliven,9 -> //| Angel) test(1) //> res0: String = Anliven test(9) //> res1: String = Angel test.contains(1) //> res2: Boolean = true test.contains(2) //> res3: Boolean = false test.keys //> res4: Iterable[Int] = Set(1,9) test.values //> res5: Iterable[String] = MapLike.DefaultValuesIterable(Anliven,Angel) test + (8 -> "888") //> res6: scala.collection.immutable.Map[Int,9 -> An //| gel,8 -> 888) test - 1 //> res7: scala.collection.immutable.Map[Int,String] = Map(9 -> Angel) test ++ List(2 -> "222",3 -> "333") //> res8: scala.collection.immutable.Map[Int,2 -> 222,3 -> 333) test ++ List(2 -> "222",3 -> "333") -- List(1,9) //> res9: scala.collection.immutable.Map[Int,String] = Map(2 -> 222,3 -> 333) 映射的遍历
循环遍历映射的基本格式:for ((k,v) <- 映射) 语句块
可以同时遍历k和v,也可以只遍历映射中的k或者v
val test3 = Map("1" -> "AAA","2" -> "BBB","3" -> "CCC") //> test3 : scala.collection.immutable.Map[String,String] = Map(1 -> AAA,2 -> B //| BB,3 -> CCC) for ((k,v) <- test3) printf("Key is : %s and Value is: %sn",k,v) //> Key is : 1 and Value is: AAA //| Key is : 2 and Value is: BBB //| Key is : 3 and Value is: CCC for (k <- test3.keys) println(k) //> 1 //| 2 //| 3 for (v <- test3.values) println(v) //> AAA //| BBB //| CCC for (x <- test3) println(x) //> (1,AAA) //| (2,BBB) //| (3,CCC) 4- Range与Stream
1 to 10 //> res0: scala.collection.immutable.Range.Inclusive = Range 1 to 10 1 to 10 by 2 //> res1: scala.collection.immutable.Range = inexact Range 1 to 10 by 2 (1 to 10).toList //> res2: List[Int] = List(1,5,6,7,9,10) 1 until 10 //> res3: scala.collection.immutable.Range = Range 1 until 10 1 until 10 by 2 //> res4: scala.collection.immutable.Range = inexact Range 1 until 10 by 2 1 #:: 2 #:: 3 #:: Stream.empty //> res5: scala.collection.immutable.Stream[Int] = Stream(1,?) val stream = (1 to 123456789).toStream //> stream : scala.collection.immutable.Stream[Int] = Stream(1,?) stream.head //> res6: Int = 1 stream.tail //> res7: scala.collection.immutable.Stream[Int] = Stream(2,?) 5- Tuple
与数据库的记录概念类似
(1,2) //> res0: (Int,Int) = (1,2) 1 -> 2 //> res1: (Int,2) (1,"Alice","Math",95.5) //> res2: (Int,String,Double) = (1,Alice,Math,95.5) val test = (1,95.5) //> test : (Int,95.5) test._1 //> res3: Int = 1 test._2 //> res4: String = Alice test._3 //> res5: String = Math test._4 //> res6: Double = 95.5 val test2 = List(1,5) //> test2 : List[Int] = List(1,5) def sumSq(in: List[Int]): (Int,Int,Int) = in.foldLeft((0,0))((t,v) => (t._1 + 1,t._2 + v,t._3 + v * v)) //> sumSq: (in: List[Int])(Int,Int) sumSq(test2) //> res7: (Int,Int) = (5,15,55) 6- 集合操作Map操作与flatMap操作
Map操作是针对集合的典型变换操作,主要用作元素的转换。
Map操作将某个函数应用到集合中的每个元素,并产生一个结果集合。
示例:给定一个字符串列表,我们可以通过map操作对列表的中每个字符串进行变换,变换后可以得到一个新的集合。
val test = List[String]("x","y","z") //> test : List[String] = List(x,z) test.map(x => x.toUpperCase) //> res0: List[String] = List(X,Y,Z) test.map(_.toUpperCase) //> res1: List[String] = List(X,Z) val test2 = List(1,5) test2.filter(x => x % 2 == 1) //> res2: List[Int] = List(1,5) test2.filter(_ % 2 == 1) //> res3: List[Int] = List(1,5) test2.filter(_ % 2 == 1).map(_ + 10) //> res4: List[Int] = List(11,13,15) val test3 = List(test2,List(6,0)) //> test3 : List[List[Int]] = List(List(1,5),0)) test3.map(x => x.filter(_ % 2 == 0)) //> res5: List[List[Int]] = List(List(2,4),0)) test3.map(_.filter(_ % 2 == 0)) //> res6: List[List[Int]] = List(List(2,0)) test3.flatMap(_.filter(_ % 2 == 0)) //> res7: List[Int] = List(2,0)
flatMap操作是Map操作的一种扩展。
在flatMap中传入一个函数,该函数对每个输入都会返回一个集合(而不是一个元素),然后,flatMap把生成的多个集合“拍扁”成为一个集合。
val myStr = List("AAA","BBB","CCC") //> myStr : List[String] = List(AAA,BBB,CCC) myStr flatMap (s => s.toList) //> res0: List[Char] = List(A,A,B,C,C) myStr.flatMap(s => s.toList) //> res1: List[Char] = List(A,C) 示例说明:对于列表myStr中的每个元素,都执行Lamda表达式定义的匿名函数“s => s.toList”,myStr中的每个元素都调用toList,生成一个字符集合List[Char],最后,flatMap把这些集合中的元素“拍扁”得到一个集合List。 filter操作
filter操作:遍历一个集合并从中获取满足指定条件的元素组成一个新的集合。
filter操作还可以做进一步操作,例如:过滤指定内容开头的元素等。
val testMap = Map(11 -> "ABC",22 -> "BCD",33 -> "CDE") //> testMap : scala.collection.immutable.Map[Int,String] = Map(11 -> ABC,22 -> //| BCD,33 -> CDE) val testFilter = testMap filter { kv => kv._2 contains "BC" } //> testFilter : scala.collection.immutable.Map[Int,22 //| -> BCD) testFilter foreach { kv => println(kv._1 + ":" + kv._2) } //> 11:ABC //| 22:BCD val testMap2 = Map(1 -> "ab",2 -> "ac",3 -> "bc") //> testMap2 : scala.collection.immutable.Map[Int,String] = Map(1 -> ab,2 -> a //| c,3 -> bc) val testFilter2 = testMap2 filter { kv => kv._2 startsWith "a" } //> testFilter2 : scala.collection.immutable.Map[Int,2 - //| > ac) testFilter2 foreach { kv => println(kv._1 + ":" + kv._2) } //> 1:ab //| 2:ac reduce操作(归约)与fold操作(折叠)
reduce操作(归约)
val test = List(1,5) test.reduceLeft((x,y) => x + y) //> res0: Int = 15 test.reduceLeft(_ + _) //> res1: Int = 15 test.reduceRight(_ + _) //> res2: Int = 15 test.reduceLeft(_ - _) //> res3: Int = -13 test.reduceRight(_ - _) //> res4: Int = 3 test.reduce(_ - _) //> res5: Int = -13
示例说明:
fold操作(折叠)
fold操作和reduce操作类似,但需要指定一个初始值,并以该值作为上下文,处理集合中的每个元素。
fold函数需要两个参数,一个参数是初始种子值,另一个参数是用于计算结果的累计函数。
包含foldLeft()和foldRight()两种操作。
fold默认采用的是foldLeft,其原型:
foldLeft(z: U)(op: (U,T) => U)
val test = List(1,5) test.foldLeft(0)(_ + _) //> res0: Int = 15 test.foldRight(0)(_ + _) //> res1: Int = 15 test.foldLeft(0)(_ - _) //> res2: Int = -15 test.foldRight(0)(_ - _) //> res3: Int = 3 test.fold(0)(_ - _) //> res4: Int = -15 test.fold(10)(_ * _) //> res5: Int = 1200
示例说明:
执行test.fold(10)(_ * _)时,首先把初始值拿去和list中的第一个值1做乘法操作,得到累乘值10,然后再拿这个累乘值10去和list中的第2个值2做乘法操作,得到累乘值20,依此类推,一直得到最终的累乘结果1200。
7- 实例WordCount
按照函数式编程的风格,编写一个程序,对某个目录下所有文件中的单词进行词频统计。
1 - 在目录“D:Anliven-RunningZenScalaProjetstemptest”创建如下两个文件:
word1.txt
this is a test ! 1,3 4,9 word2.txt? 1,9 4,9 this is a test ! 2 - 编辑并运行如下代码: package testscala import java.io.File import scala.io.Source object TestScala { def main(args: Array[String]): Unit = { val dirfile = new File("D:Anliven-RunningZenScalaProjetstemptest") val files = dirfile.listFiles //得到数组files for (file <- files) println(file) //遍历数组 val aFilesList = files.toList //Array类的toList方法将连续存放的数组转换为递归存放的列表 val wordsMap = scala.collection.mutable.Map[String,Int]() //定义一个Map变量,key是单词,value是单词数量 aFilesList.foreach( file => Source.fromFile(file).getLines().foreach( line => line.split(" ").foreach( word => { if (wordsMap.contains(word)) { wordsMap(word) += 1 } else { wordsMap += (word -> 1) } }))) println(wordsMap) //打印内容 for ((key,value) <- wordsMap) println(key + ": " + value) //遍历内容 } }
代码说明:
3 - 运行结果: D:Anliven-RunningZenScalaProjetstemptestword1.txt D:Anliven-RunningZenScalaProjetstemptestword2.txt Map(is -> 2,3 -> 2,a -> 2,9 -> 3,! -> 2,this -> 2,test -> 2) is: 2 1,3: 2 a: 2 4,9: 3 !: 2 this: 2 test: 2 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |