今天在寫一個統計用戶信息的程序時出現了bug,導致統計結果與真實值有很大差距。經過仔細檢查,我發現是錯誤地使用split函數導致的。看來還是對scala中的split函數的理解不夠透徹。本篇博文將詳細解釋scala中String.split的參數及用法。
因為scala中的String復用了Java的String,因此這也是Java中String.split的用法。
split函數主要有兩種參數形式:
def split(arg0: String): Array[String]
def split(arg0: String, arg1: Int): Array[String]
我們可以將第一種參數形式看作是默認arg1=0的第二種形式,即調用split(StrToSplit)等同於調用了split(StrToSplit, 0)。因此,我將主要介紹第二種參數形式。第二種參數形式中每個參數的意義如下:
arg0: String 是一個正則表達式,代表分割的邊界。這個正則表達式成功匹配一次,split的結果中就會加入一個新的子串。子串包含上次匹配后(如果沒有上次匹配就是被分割字符串的起始位置)到這次匹配前的所有字符。最后,split函數會將最后一次匹配后剩余的字串作為最后一個子串加入到結果中。
arg1: Int 是對分割后子串的個數的限定。理解這個參數才能正確的運用split函數。
當arg1大於0時,它限制arg0最多成功匹配arg1-1次,也就是說字符串最多被分成arg1個子串。此時split會保留分割出的空字符串(當兩個arg0連續匹配活着arg0在頭尾匹配,會產生空字符串),直到達到匹配上限。比如:
1 scala> "a-b-c".split("-", 2) 2 res38: Array[String] = Array(a, b-c) 3 4 scala> "a-b-c".split("-", 4) 5 res39: Array[String] = Array(a, b, c) 6 7 scala> "-a-b-c--".split("-", 3) 8 res40: Array[String] = Array("", a, b-c--) 9 10 scala> "-a-b-c--".split("-", 6) 11 res41: Array[String] = Array("", a, b, c, "", "") 12 13 scala> "-a-b-c--".split("-", 5) 14 res42: Array[String] = Array("", a, b, c, -) 15 16 scala> "-a-b-c--".split("-", 8) 17 res43: Array[String] = Array("", a, b, c, "", "")
當arg1等於0時,split函數會盡可能多的匹配arg0,但不再保留處於末尾位置的空字符串(這里的一個特殊情況是,當被分割字符串是一個空字符串時,分割結果仍是一個空字符串組成的數組)。比如:
1 scala> "a-b-c".split("-", 0) 2 res48: Array[String] = Array(a, b, c) 3 4 scala> "a-b-c---".split("-", 0) 5 res49: Array[String] = Array(a, b, c) 6 7 scala> "-a--b--c---".split("-", 0) 8 res50: Array[String] = Array("", a, "", b, "", c) 9 10 scala> "".split("-", 0) 11 res51: Array[String] = Array("")
當arg1小於0時,split函數會盡可能多的匹配arg0,並且保留末尾的空字符串。比如:
1 scala> "a-b-c".split("-", -1) 2 res52: Array[String] = Array(a, b, c) 3 4 scala> "-a--b--c-".split("-", -1) 5 res53: Array[String] = Array("", a, "", b, "", c, "")