What split does
The split function cuts a string at every occurrence of a delimiter and returns the pieces. In Kotlin the result is a List<String>, not an array. The delimiter itself is not part of any piece.
val sentence = "hello world foo"
val words = sentence.split(" ")
// [hello, world, foo]
val csv = "a,b,c"
val parts = csv.split(",")
// [a, b, c]
The delimiter you pass as a string is matched literally. A dot, for example, is just a dot: "a.b".split(".") gives [a, b], with no pattern tricks to worry about. If you do want a pattern, pass a Regex, which is covered below.
Working with the resulting list
A list has a size, can be read by index, and can be looped over:
val words = "hello world foo".split(" ")
println(words.size) // 3
println(words[1]) // world
for (w in words) {
println(w)
}
The loop prints hello, world and foo, one per line. Reading a position that is not there, such as words[3], throws an IndexOutOfBoundsException, in the same way a string index can go out of bounds.
When you know how many pieces to expect, you can unpack them in one line: val (key, value) = "x:y".split(":") puts x in key and y in value.
The exercise
The lesson provides sentence and asks for a new value, words, holding its words:
- Pick the delimiter. The words are separated by single spaces, so the delimiter is
" ". - Call
splitonsentenceand store the result inwords. It is declared withvalbecause the list is never reassigned. Kotlin infers its type,List<String>.
val sentence = "hello world foo"
val words = sentence.split(" ")
Now words holds the three strings hello, world and foo, and sentence is unchanged.
Empty pieces
Kotlin keeps empty pieces. Two delimiters in a row produce an empty string between them, and a delimiter at the very start or end produces an empty string at that end:
println("a b c".split(" ")) // [a, b, , c]
println("a,b,,".split(",")) // [a, b, , ]
println(" a b ".split(" ")) // [, a, b, ]
println("".split(",").size) // 1
The last line shows that splitting an empty string gives a list with one element, the empty string, not an empty list. Empty pieces are a common cause of surprises when the input comes from a person, because extra spaces are easy to type.
Two remedies are common. Drop the empties after splitting, or split on a pattern that treats a run of whitespace as one delimiter:
println("a b c".split(" ").filter { it.isNotEmpty() }) // [a, b, c]
println("a b c".split(Regex("\\s+"))) // [a, b, c]
The pattern \s+ means "one or more whitespace characters". Note that it still produces an empty piece at the start if the string begins with a space, so trim the string first if that can happen.
More than one delimiter, and a limit
You can pass several delimiters, and any one of them cuts the string. A limit caps the number of pieces; the last piece keeps the rest of the text:
println("a,b;c".split(",", ";")) // [a, b, c]
println("k=v=w".split("=", limit = 2)) // [k, v=w]
The reverse: joining
To put the pieces back together, use joinToString with the separator you want:
println("one two".split(" ").joinToString("-")) // one-two
Splitting and joining are often used as a pair: split a line into words, change them, and join them again with a different separator.
Common mistakes
- Expecting an array.
splitreturns aList, so usesizeandwords[i], notlength. - Forgetting empty pieces. Doubled delimiters and delimiters at the ends give empty strings.
- Converting too soon.
"1 2 3".split(" ")holds strings. To add the numbers you must convert them, for examplemap { it.toInt() }. - Using a pattern character as plain text. With a string delimiter there is no escaping to do:
split(".")andsplit("|")split on those exact characters. - Using the wrong quotes.
split(" ")takes a string, andsplit(' ')takes a character. Both work and give the same result, but be consistent.
Key takeaways
s.split(delimiter)returns aList<String>, with the delimiter removed.- A string delimiter is literal; pass a
Regexfor patterns. - Empty pieces are kept, so splitting needs a plan for extra delimiters.
- Use
size, indexes andforloops to work with the result.