往期回顾
前言
在上一期的《大数据之脚踏实地学15--Scala的数组操作》分享中,介绍了Scala的数组相关知识,借助于Array函数可以构造定长数组(即数组一旦定义好长度,就无法对元素个数做影响),而通过ArrayBuffer函数则可以构造变长数组。在本期中将介绍Scala的其他常用的数据结构,包括列表、元组和映射。
列表
Scala中的列表与之前分享的数组有一些相似之处,例如列表中的元素也需要具有相同的数据类型、对于不可变列表而言,其长度也是固定的。但也有一些差异,例如对于不可变数组的创建,需要提前指定数组元素的长度,而不可变列表无需指定长度便可直接构造、数组属于可变对象(即数组的元素可以被修改),而列表不是可变对象。接下来通过一些简单的实例,来接受列表的相关知识点。
列表的构造
不可变列表的构造只需要使用List函数就可以轻松搞定,一旦构造好后,其元素便不可以变动,包括列表元素的增加、删除和修改。当然,如果工作中需要对列表元素进行修改,可以构造可变列表,使用ListBuffer函数即可,该函数需要导入scala.collection.mutable模块
// 构造不可变列表val ls1 = List("apple","orange","banana","dog","cat","monkey","pig")val ls2 = List(10,22,16,4,8)// 构造可变列表import scala.collection.mutablevar ls3 = mutable.ListBuffer(1,1,2,3,5,8,13)
首先介绍一下可变列表的增删改操作,然后再介绍可变列表与不可以列表都可以使用的一些常规方法。
列表的增删改操作
可变列表的增
对于可变列表而言,可以借助于append方法在列表的末尾增加一个或多个元素;使用+=方法在末尾增加一个元素;使用++=方法追加另一个列表;使用insert方法在列表的指定位置增加一个元素。
// 列表元素的增加ls3.append(21,36) // 增加多个元素println("ls3 = " + ls3)ls3.+=(57) // 增加一个元素println("ls3 = " + ls3)ls3.++=(ls2) // 将一个列表添加到可变列表中println("ls3 = " + ls3)ls3.insert(3,100) // 在指定位置插入元素println("ls3 = " + ls3)// 结果输出ls3 = ListBuffer(1, 1, 2, 3, 5, 8, 13, 21, 36)ls3 = ListBuffer(1, 1, 2, 3, 5, 8, 13, 21, 36, 57)ls3 = ListBuffer(1, 1, 2, 3, 5, 8, 13, 21, 36, 57, 10, 22, 16, 4, 8)ls3 = ListBuffer(1, 1, 2, 100, 3, 5, 8, 13, 21, 36, 57, 10, 22, 16, 4, 8)
可变列表的删
对于列表元素的删除也有一些基本的方法,例如trimStart方法删除列表开头的几个元素;trimEnd则可以删除列表末尾的几个元素;-=方法则可以删除指定的列表元素;clear方法还可以对列表元素做清空处理。
// 列表元素的删除ls3.trimStart(2) // 删除列表开头的两个元素println("ls3 = " + ls3)ls3.trimEnd(2) // 删除列表结尾的两个元素println("ls3 = " + ls3)ls3.-=(2,22) // 删除指定的值println("ls3 = " + ls3)// 结果输出ls3 = ListBuffer(2, 100, 3, 5, 8, 13, 21, 36, 57, 10, 22, 16, 4, 8)ls3 = ListBuffer(2, 100, 3, 5, 8, 13, 21, 36, 57, 10, 22, 16)ls3 = ListBuffer(100, 3, 5, 8, 13, 21, 36, 57, 10, 16)
可变列表的改
如果工作中设计到可变列表元素的修改时,便可以借助于“取而代之”的思想实现元素之的修改。具体操作如下:
// 列表元素的修改ls3(8) = 900 // 将第9个元素改为900println("ls3 = " + ls3)ls3.update(4,400) // 将第5个元素改为400println("ls3 = " + ls3)// 结果输出ls3 = ListBuffer(100, 3, 5, 8, 400, 21, 36, 57, 10, 16)ls3 = ListBuffer(100, 3, 5, 8, 400, 21, 36, 57, 900, 16)
列表的其他操作
尽管不可变列表存在一些缺陷,但这不代表它只是一个容器,它还可以做其他事。接下来所要介绍的内容不局限于不可变列表,可变列表也具有相同的操作权限。具体代码案例如下:
// 列表元素的查询println("列表ls1的第3个元素是:" + ls1(2))println("列表ls3元素的切片(第4个至第8个元素):" + ls3.slice(3,8))println("根据条件筛选列表ls2的元素:" + ls2.filter(_>=10))// 列表元素的删除 -- 需要注意的是,如下方法均不可以之间改变列表本身println("删除列表前两个元素:" + ls2.drop(2))println("删除列表后两个元素:" + ls2.dropRight(2))// dropWhile:从左向右丢弃元素,直到条件不成立println("删除首批大于等于10的元素:" + ls2.dropWhile(_ >= 10))// 列表的属性println("列表ls1的元素个数为:" + ls1.length)println("列表ls3中偶数的个数:" + ls3.count(_ % 2 == 0))println("列表ls2元素的排序:" + ls2.sorted) // 如需降序,再使用reverse方法println("返回列表ls2中首次大于12的元素:" + ls2.find(_ > 12))// indexOf方法如果找不到元素的位置则返回-1println("返回ls2中元素值为12的首次位置:" + ls2.indexOf(12))/* 常规统计函数的属于ls2.length -- 计数ls2.sum -- 求和ls2.min -- 最小值ls2.max -- 最大值*/// 列表ls3与ls2的差集println("差集为:" + ls3.diff(ls2))// 列表元素的拼接,结果为字符型对象println("列表元素的拼接:" + ls2.mkString(","))// 结果输出列表ls1的第3个元素是:banana列表ls3元素的切片(第4个至第8个元素):ListBuffer(8, 400, 21, 36, 57)根据条件筛选列表ls2的元素:List(10, 22, 16)ls2 = List(10, 22, 16, 4, 8)删除列表前两个元素:List(16, 4, 8)删除列表后两个元素:List(10, 22, 16)删除首批大于等于10的元素:List(4, 8)列表ls1的元素个数为:7列表ls3中偶数的个数:6列表ls2元素的排序:List(4, 8, 10, 16, 22)返回ls2中首次大于12的元素:Some(22)返回ls2中元素值为12的首次位置:-1差集为:ListBuffer(100, 3, 5, 400, 21, 36, 57, 900)列表元素的拼接:10,22,16,4,8
元组的构造
元组与列表类似,同样属于不可变对象,所不同的是,列表中的元素是同类型的,元组的元素可以是不同类型的。而且还有一个非常大的区别,列表元素的索引从0开始,而元组则是从1开始,并且两种数据结构的索引写法也不相同。
// 元组的构造--使用一对圆括号即可val t1 = (1,"First",5.5,"Monday",false,'A',100002345)// 元组元素的获取println("元组的第三个元素:" + t1._3)// 结果输出元组的第三个元素:5.5
相比于列表而言,元组可用的方法就少了很多,例如length方法、filter方法、drop方法、count方法等。如果你想使用列表的那些常规方法,也是可以的,那就对元组再使用productIterator方法,便可以基于此使用列表的其他方法了。
println("删除开头的两个元素:" )t1.productIterator.drop(2).foreach(println)// 结果输出删除开头的两个元素:5.5MondayfalseA100002345
映射的构造
映射与Python的字典类似,映射的元素是由一对键值对构成的,映射也分为不可变映射和可变映射。借助于Map函数构造不可变映射,元素可以写成key -> value的形式,也可以写成(key,value)的形式。
// 不可变映射val info = Map("name" -> "Snake", "gender" -> "男", "age" -> 30, ("height",170), "score" -> 88)// 可变映射var RFM = mutable.Map("Recency" -> 37, ("Frequency",8), "Money" -> 3274)
可变映射的增删改
// 元素的增加RFM.+=(("Uid" -> 213244532))println("RFM = " + RFM)// 元素的删除RFM.-=("Frequency")println("RFM = " + RFM)// 元素的修改RFM("Money") = 3330RFM.update("Recency", 307)println("RFM = " + RFM)// 结果输出RFM = Map(Frequency -> 8, Money -> 3274, Uid -> 213244532, Recency -> 37)RFM = Map(Money -> 3274, Uid -> 213244532, Recency -> 37)RFM = Map(Money -> 3330, Uid -> 213244532, Recency -> 307)
映射的其他常用方法
// 映射元素的查询println("info中name键对应的值:" + info("name"))println("info中score键对应的值:" + info.get("score"))// 返回映射的键、值、键值对println("映射的键为:" + info.keySet)println("映射的值为:" + info.values)println("映射的键值对为:" + info.toList)// 结果输出info中name键对应的值:Snakeinfo中score键对应的值:Some(88)映射的键为:Set(name, score, height, age, gender)映射的值为:MapLike.DefaultValuesIterable(Snake, 88, 170, 30, 男)映射的键值对为:List((name,Snake), (score,88), (height,170), (age,30), (gender,男))
结语
本期的内容就介绍到这里,如果你有任何问题,欢迎在公众号的留言区域表达你的疑问。同时,也欢迎各位朋友继续转发与分享文中的内容,让更多的人学习和进步。
每天进步一点点:数据分析1480
长按扫码关注我