前言
在之前的Scala系列中分享了有关数据类型、运算符操作、控制流语法、自定义函数、以及几种集合的使用。慢慢地Scala体系将越来越丰富,在本期内容中将跟各位网友分享Scala的字符串操作和正则表达式的巧用。
字符串操作
字符串是最为常见的一种数据类型,在平时的学习或工作中总能碰见关于字符串的处理,例如字符串的拼接、替换、截取、判断、分割等。接下来对常用的字符串处理做详细讲解,并通过实际的例子加以说明。
字符串的创建
字符串与前几期介绍的列表、元组一样,都属于属于不可变对象,无法通过其方法实现字符串本身的修改。字符串的创建可以使用两种方法,分别是:
双引号法 三对双引号法
我们知道,在Scala中利用单引号可以创建字符对象,而双引号则可以构造字符串对象。但双引号方法构造字符串会存在一个隐患,那就是字符串本身含有双引号是,就会出现语法错误。此时的解决方案就是将双引号换成三引号,而且三引号更强大的地方,可以使字符串多行显示。下面来看几个小例子:
代码语言:javascript复制// 字符串自带双引号时,使用双引号构造字符串,出现报错
scala> val S1 = "He says: "see you tomorrow!""
<console>:11: error: value see is not a member of String
val S1 = "He says: "see you tomorrow!""
// 解决方案,使用三引号
scala> val S2 ="""He says: "see you tomorrow!""""
S2: String = He says: "see you tomorrow!"
// 多行显示字符串值
val S3 ="""大家好,我是刘顺祥。
|很高兴跟大家分享Scala的点滴知识,
|感谢大家的支持和鼓励,谢谢!"""
S3: String =
大家好,我是刘顺祥。
很高兴跟大家分享Scala的点滴知识,
感谢大家的支持和鼓励,谢谢!
字符串子串的获取
如需从字符串中获取其中的子部分,可以使用Scala字符串的索引和切片技术。需要注意的是,索引的写法不是中括号[],而是圆括号(),这跟其他编程语言有一些差异。而切片的使用,则调用的是字符串方法slice。相关知识点如下:
charAt:基于位置取出字符串中的某个字符,结果属于Char类型; 索引():等价于charAt的使用; slice切片:从字符串中获取连续的一小段; substring:等同于slice切片的操作;
举例
代码语言:javascript复制val price1 = "3元/500g"
println(price1.charAt(0))
3 // 3为Char类型
// 索引方法,如需将字符3转换成整数,必须先转为字符串,
//才可以使用toInt,否则结果有误
println(price1(0).toString.toInt)
3 // 3为整型
val price2 = "36.2元/500g"
// 切片slice方法中的实参4所对应的值取不到
println(price2.slice(0,4).toDouble)
36.2
// substring方法的功能等同于slice方法
println(price2.substring(0,4))
36.2
// 配合length方法(该方法计算字符长度),
// 灵活使用切片,取出末尾的4个字符
println(price2.slice(price2.length-4, price2.length))
500g
字符串的拼接
拼接是指将两个或多个字符串进行首尾相连,实现的方法也很简单,具体如下:
:字符串之间通过加号实现拼接; concate:利用字符串的concate方法; *:字符串乘以一个整数,指的是字符串的重复
举例
代码语言:javascript复制val a = "Hello, "
val b = "Scala!"
println(a b )
Hello, Scala!
println(a.concat(b))
Hello, Scala!
println(b * 3) // 重复三遍
Scala!Scala!Scala!
字符串子串位置的查询
在使用切片时可能会碰到开始位置或结束位置的不确定,如果只写上一个固定的整数位置,将无法体现切片的效果。例如价格"23.4元/500g",需要提取出其中的数值23.4,就不能写死切片的开始位置和结束位置,因为万一有"234.5元/500g"的价格就会遇到麻烦。最好的解决方案就是查询字符串中"元"所在的位置,然后再使用切片技术。知识点如下:
indexOf:返回子串首次出现的位置; lastIndexOf:返回子串最后一次出现的位置;
举例
代码语言:javascript复制println(b.indexOf("a")) // 返回第一个"a"所在的位置
2
println(b.lastIndexOf("a")) // 返回最后一个"a"所在的位置
4
println(price2.slice(0,price2.indexOf("元")))
36.2
字符串首尾空白的去除
如果在数据清洗过程中,发现字符串的首尾可能存在空白,你可以使用trim方法轻松的将其删除掉,举例如下:
代码语言:javascript复制val S4 = " 今天晨跑让自己一天的心情都非常好,明天继续! "
println(S4.trim) // 删除字符串首尾空白
今天晨跑让自己一天的心情都非常好,明天继续!
字符串的替换
字符串中子串的替换也是非常常见的一种操作,如需遇到这种情况,你可以使用如下几个字符串方法:
replace:字符串方法,根据指定的值进行替换; replaceFirst:替换第一个满足条件的值,支持正则表达式的使用; replaceAll:替换所有满足条件的值,支持正则表达式的使用;
举例
代码语言:javascript复制val S5 = "我是Scala用户,觉得Scala很简单!"
println(S5.replace("Scala","Python"))
我是Python用户,觉得Python很简单!
println(S5.replaceFirst("Scala","Python"))
我是Python用户,觉得Scala很简单!
println(S5.replaceAll("Scala","Python"))
我是Python用户,觉得Python很简单!
再举一个有意思的小例子,前文中提到,利用三引号可以将长字符串进行多行显示,如果需要将多行的字符串切换到一行显示该如何处理呢?很简单,只需要使用replaceAll方法,将字符串中的换行符"n"替换为空字符""即可。代码如下:
代码语言:javascript复制val S6 = """今天晨跑让自己一天的心情都非常好,
|明天继续!"""
// stripMargin方法默认以竖线"|"作为分界符,将字符串垂直对齐
println(S6.stripMargin.replaceAll("n"," "))
今天晨跑让自己一天的心情都非常好, 明天继续!
字符串的分割
有时需要对字符串的内容进行分割,往往分割的时候是需要指定分割符的,最典型的是类似于Excel中的分列操作。在Scala中可以使用如下函数实现字符串的分割:
split:可以指定具体的分割符,也可以指定一个模糊的正则表达式 splitAt:按照字符串的位置进行分割
举例
代码语言:javascript复制val S7 = "lsxxx2017@163.com"
println(S7.split('@').toVector) // 根据指定的分隔符将字符串切开
Vector(lsxxx2017, 163.com)
println(S7.split("@").toList) // 支持正则表达式的使用
List(lsxxx2017, 163.com)
println(S7.splitAt(9)) // 根据字符串的位置将字符串切开
(lsxxx2017,@163.com)
字符串的比较
如需判断两个字符串之间是否相等,或者字符串是否以某个子串开头或结尾,可以使用如下几个方法加以实现:
==:判断两者是否相等; equals:等同于双等号法; equalsIgnoreCase:比较时忽略大小写; startsWith:判断字符串是否以某子串开头; endsWith:判断字符串是否以某子串结尾;
举例
代码语言:javascript复制val S8 = "Scala"
val S9 = "scala"
println(S8 == S9)
false
println(S8.equals(S9))
false
println(S8.equalsIgnoreCase(S9))
true
println(S9.startsWith("sc"))
true
println(S9.endsWith("sc"))
false
字符串的迭代
字符串属于可迭代对象,可以针对字符串中的每一个字符做相同函数的处理。读者可以使用如下三种方法完成字符串的迭代操作:
foreach:该方法迭代过程中没有返回值; map:有返回值,它是由一个集合到另一个集合的运算; for yield:功能同map方法,而且该方法还可以编写更加复杂的代码;
举例
代码语言:javascript复制val S10 = "Spark is based on Scala"
// 必须将foreach出来的每个Char对象做toString的转换,否则出错
S10.foreach(x => print(x.toString.toUpperCase))
SPARK IS BASED ON SCALA
println(S10.map(_.toUpper))
SPARK IS BASED ON SCALA
// 由一个集合到另一个集合的运算
val res = for (i <- S10) yield i.toUpper
println(res)
SPARK IS BASED ON SCALA
字符串的插值
字符串的插值操作类似于Python中字符串的格式化处理,可以在字符串的内部引入变量值,甚至书写数学表达式或者对变量值做格式化输出。Scala中有两种风格的插值方法,一种是s法,另一种是f法:
s格式插值,可以书写变量表达式; f格式插值,除了拥有s法的功能,还可以格式化数据
举例
代码语言:javascript复制val name = "Liu"
val height = 165
val weight = 65
println(s"""亲爱的${name}先生,您的身高是${height},体重是${weight},
|身体质量指数是${weight/((1.0*height/100)*(1.0*height/100))}!""".stripMargin)
亲爱的Liu先生,您的身高是165,体重是65,
身体质量指数是23.875114784205696!
println(f"""亲爱的${name}先生,您的身高是${height},体重是${weight},
|身体质量指数是${weight/((1.0*height/100)*(1.0*height/100))}%.2f!""".stripMargin)
亲爱的Liu先生,您的身高是165,体重是65,
身体质量指数是23.88!
结语
本期的内容就介绍到这里,下一期的Scala内容讲分享有关正则表达式的使用。如果你有任何问题,欢迎在公众号的留言区域表达你的疑问。同时,也欢迎各位朋友继续转发与分享文中的内容,让更多的人学习和进步。
每天进步一点点:数据分析1480
长按扫码关注我
往期回顾
大数据之脚踏实地学16--Scala列表、元组与映射 大数据之脚踏实地学15--Scala的数组操作 大数据之脚踏实地学14--Scala自定义函数 大数据之脚踏实地学13--Scala控制流