Getting the length
The length method returns the number of characters in a string as an Int:
var message = "Hello world"
println(message.length) // 11
message += "!"
println(message.length) // 12
Spaces and punctuation count. Because strings are immutable, message += "!" builds a new, longer string and stores it in the var, so the length is read from the new string. length is a Java method, so message.length() works too, and so does message.size.
Counting from the end
Indexes run from 0 to length - 1, so the last character is at length - 1. In general, the nth character from the end is at length - n:
val message = "Hello world"
val length = message.length
println(message(length - 1)) // d
println(message(length - 2)) // l
The same idea gives the last n characters of a string: start the substring at length - n and run to the end.
println(message.substring(length - 4)) // orld
println(message.substring(length - 7)) // o world
The exercise, step by step
The lesson starts with val message = "I love pancakes", which has 15 characters.
- Print the length.
message.lengthgives 15. - Print the last character. Its index is
message.length - 1, which is 14, somessage(message.length - 1)iss. - Print the last 5 characters. They start at index
message.length - 5(10) and end at the end of the string. The lesson passes the end explicitly:substring(message.length - 5, message.length). The one-argument form gives the same result.
val message = "I love pancakes"
println(message.length)
println(message(message.length - 1))
println(message.substring(message.length - 5, message.length))
15
s
cakes
Pitfalls
- Off by one. The length is one more than the last index.
message(message.length)throws aStringIndexOutOfBoundsExceptionwith the messageIndex 15 out of bounds for length 15. - Empty strings. For
""the length is 0, sos(s.length - 1)asks for index -1 and throws. Checks.nonEmptyfirst when the string might be empty. - Taking too many characters.
substring(length - n)fails whennis larger than the length, because the start becomes negative. For short strings,takeRight(n)returns the whole string instead of throwing. - Characters versus code units.
lengthcounts 16-bit units. Most text is fine, but an emoji such as"😀"counts as 2.
Empty strings and loops
The empty string "" has length 0. Instead of comparing the length to 0, you can ask isEmpty or nonEmpty:
println("".isEmpty) // true
println("ab".nonEmpty) // true
println("a b c".length) // 5
The length also controls loops. for (i <- 0 until s.length) visits every index of s exactly once. Writing 0 to s.length would include the length itself, which is not a valid index.
Why length - 1 and not length
Counting and indexing start from different places. Counting starts at 1, so the last item is the nth. Indexing starts at 0, so the last item has index n - 1. For "I love pancakes", the answer to "how many characters?" is 15, but the answer to "where is the last one?" is 14. Keep these two questions apart and most index arithmetic becomes routine.
Using the length in other calculations
The length is an ordinary Int, so you can do arithmetic with it. Integer division truncates, so s.length / 2 is the index of the middle character of an odd-length string: for "abcde" it is 2, and "abcde"(2) is c. For an even length such as 4 it is 2, which is the right-hand one of the two middle characters. Always make sure the string is not empty before indexing with a value computed from its length.
Key takeaways
s.lengthis the number of characters, and the last index iss.length - 1.- The last character is
s(s.length - 1). - The last n characters are
s.substring(s.length - n).
