往期回顾
大数据之脚踏实地学15--Scala的数组操作
前言
在上一期的《大数据之脚踏实地学15--Scala的数组操作》分享中,介绍了Scala的数组相关知识,借助于Array函数可以构造定长数组(即数组一旦定义好长度,就无法对元素个数做影响),而通过ArrayBuffer函数则可以构造变长数组。在本期中将介绍Scala的其他常用的数据结构,包括列表、元组和映射。
列表
Scala中的列表与之前分享的数组有一些相似之处,例如列表中的元素也需要具有相同的数据类型、对于不可变列表而言,其长度也是固定的。但也有一些差异,例如对于不可变数组的创建,需要提前指定数组元素的长度,而不可变列表无需指定长度便可直接构造、数组属于可变对象(即数组的元素可以被修改),而列表不是可变对象。接下来通过一些简单的实例,来接受列表的相关知识点。
列表的构造
不可变列表的构造只需要使用List函数就可以轻松搞定,一旦构造好后,其元素便不可以变动,包括列表元素的增加、删除和修改。当然,如果工作中需要对列表元素进行修改,可以构造可变列表,使用ListBuffer函数即可,该函数需要导入scala.collection.mutable模块
代码语言:javascript复制// 构造不可变列表
val ls1 = List("apple","orange","banana","dog","cat","monkey","pig")
val ls2 = List(10,22,16,4,8)
// 构造可变列表
import scala.collection.mutable
var ls3 = mutable.ListBuffer(1,1,2,3,5,8,13)
首先介绍一下可变列表的增删改操作,然后再介绍可变列表与不可以列表都可以使用的一些常规方法。
列表的增删改操作
可变列表的增 对于可变列表而言,可以借助于append方法在列表的末尾增加一个或多个元素;使用 =方法在末尾增加一个元素;使用 =方法追加另一个列表;使用insert方法在列表的指定位置增加一个元素。
代码语言:javascript复制// 列表元素的增加
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方法还可以对列表元素做清空处理。
代码语言:javascript复制// 列表元素的删除
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)
可变列表的改 如果工作中设计到可变列表元素的修改时,便可以借助于“取而代之”的思想实现元素之的修改。具体操作如下:
代码语言:javascript复制// 列表元素的修改
ls3(8) = 900 // 将第9个元素改为900
println("ls3 = " ls3)
ls3.update(4,400) // 将第5个元素改为400
println("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)
列表的其他操作
尽管不可变列表存在一些缺陷,但这不代表它只是一个容器,它还可以做其他事。接下来所要介绍的内容不局限于不可变列表,可变列表也具有相同的操作权限。具体代码案例如下:
代码语言:javascript复制// 列表元素的查询
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方法如果找不到元素的位置则返回-1
println("返回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开始,并且两种数据结构的索引写法也不相同。
代码语言:javascript复制// 元组的构造--使用一对圆括号即可
val t1 = (1,"First",5.5,"Monday",false,'A',100002345)
// 元组元素的获取
println("元组的第三个元素:" t1._3)
// 结果输出
元组的第三个元素:5.5
相比于列表而言,元组可用的方法就少了很多,例如length方法、filter方法、drop方法、count方法等。如果你想使用列表的那些常规方法,也是可以的,那就对元组再使用productIterator方法,便可以基于此使用列表的其他方法了。
代码语言:javascript复制println("删除开头的两个元素:" )
t1.productIterator.drop(2).foreach(println)
// 结果输出
删除开头的两个元素:
5.5
Monday
false
A
100002345
映射的构造
映射与Python的字典类似,映射的元素是由一对键值对构成的,映射也分为不可变映射和可变映射。借助于Map函数构造不可变映射,元素可以写成key -> value的形式,也可以写成(key,value)的形式。
代码语言:javascript复制// 不可变映射
val info = Map("name" -> "Snake", "gender" -> "男", "age" -> 30, ("height",170), "score" -> 88)
// 可变映射
var RFM = mutable.Map("Recency" -> 37, ("Frequency",8), "Money" -> 3274)
可变映射的增删改
代码语言:javascript复制// 元素的增加
RFM. =(("Uid" -> 213244532))
println("RFM = " RFM)
// 元素的删除
RFM.-=("Frequency")
println("RFM = " RFM)
// 元素的修改
RFM("Money") = 3330
RFM.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)
映射的其他常用方法
代码语言:javascript复制// 映射元素的查询
println("info中name键对应的值:" info("name"))
println("info中score键对应的值:" info.get("score"))
// 返回映射的键、值、键值对
println("映射的键为:" info.keySet)
println("映射的值为:" info.values)
println("映射的键值对为:" info.toList)
// 结果输出
info中name键对应的值:Snake
info中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
长按扫码关注我