前言

在之前的Scala系列中分享了有关数据类型、运算符操作、控制流语法、自定义函数、以及几种集合的使用。慢慢地Scala体系将越来越丰富,在本期内容中将跟各位网友分享Scala的字符串操作和正则表达式的巧用。

字符串操作

字符串是最为常见的一种数据类型,在平时的学习或工作中总能碰见关于字符串的处理,例如字符串的拼接、替换、截取、判断、分割等。接下来对常用的字符串处理做详细讲解,并通过实际的例子加以说明。

字符串的创建

字符串与前几期介绍的列表、元组一样,都属于属于不可变对象,无法通过其方法实现字符串本身的修改。字符串的创建可以使用两种方法,分别是:

双引号法
三对双引号法

我们知道,在Scala中利用单引号可以创建字符对象,而双引号则可以构造字符串对象。但双引号方法构造字符串会存在一个隐患,那就是字符串本身含有双引号是,就会出现语法错误。此时的解决方案就是将双引号换成三引号,而且三引号更强大的地方,可以使字符串多行显示。下面来看几个小例子:

// 字符串自带双引号时,使用双引号构造字符串,出现报错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切片的操作;

举例

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方法;
*:字符串乘以一个整数,指的是字符串的重复

举例

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:返回子串最后一次出现的位置;

举例

println(b.indexOf("a")) // 返回第一个"a"所在的位置2println(b.lastIndexOf("a")) // 返回最后一个"a"所在的位置4println(price2.slice(0,price2.indexOf("元")))36.2

字符串首尾空白的去除

如果在数据清洗过程中,发现字符串的首尾可能存在空白,你可以使用trim方法轻松的将其删除掉,举例如下:

val S4 = "  今天晨跑让自己一天的心情都非常好,明天继续!   "println(S4.trim)  // 删除字符串首尾空白今天晨跑让自己一天的心情都非常好,明天继续!

字符串的替换

字符串中子串的替换也是非常常见的一种操作,如需遇到这种情况,你可以使用如下几个字符串方法:

replace:字符串方法,根据指定的值进行替换;
replaceFirst:替换第一个满足条件的值,支持正则表达式的使用;
replaceAll:替换所有满足条件的值,支持正则表达式的使用;

举例

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"替换为空字符""即可。代码如下:

val S6 = """今天晨跑让自己一天的心情都非常好,        |明天继续!"""// stripMargin方法默认以竖线"|"作为分界符,将字符串垂直对齐println(S6.stripMargin.replaceAll("\n"," "))今天晨跑让自己一天的心情都非常好, 明天继续!

字符串的分割

有时需要对字符串的内容进行分割,往往分割的时候是需要指定分割符的,最典型的是类似于Excel中的分列操作。在Scala中可以使用如下函数实现字符串的分割:

split:可以指定具体的分割符,也可以指定一个模糊的正则表达式
splitAt:按照字符串的位置进行分割

举例

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:判断字符串是否以某子串结尾;

举例

val S8 = "Scala"val S9 = "scala"println(S8 == S9)falseprintln(S8.equals(S9))falseprintln(S8.equalsIgnoreCase(S9))trueprintln(S9.startsWith("sc"))trueprintln(S9.endsWith("sc"))false

字符串的迭代

字符串属于可迭代对象,可以针对字符串中的每一个字符做相同函数的处理。读者可以使用如下三种方法完成字符串的迭代操作:

foreach:该方法迭代过程中没有返回值;
map:有返回值,它是由一个集合到另一个集合的运算;
for yield:功能同map方法,而且该方法还可以编写更加复杂的代码;

举例

val S10 = "Spark is based on Scala"// 必须将foreach出来的每个Char对象做toString的转换,否则出错S10.foreach(x => print(x.toString.toUpperCase)) SPARK IS BASED ON SCALAprintln(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法的功能,还可以格式化数据

举例

val name = "Liu"val height = 165val weight = 65println(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

大数据之脚踏实地学17--Scala字符串的清洗_字符串