Start learning free

LESSON 57 OF 348 · STRINGS I

String Slicing in Kotlin: substring, take and drop

Lesson Read the full explanation

Not only we can select a single character from a string, but we can also select a sequence of consecutive characters (e.g. substring) from a string.

To achieve this, we use the substring() method like this:

string.substring(startIndex, endIndex)

This is called slicing a string. It returns the substring from startIndex to endIndex.

Here is an example:

val language = "JavaScript"
val substring = language.substring(2, 6)

println(substring) // Output: "vaSc"
println(language) // Output: "JavaScript"

The startIndex is a zero-based index at which we start extraction and the endIndex is also zero-based index before which we end the extraction.

The substring will not include the character at endIndex. You can see in our example that the character at index 2 (v) was included while the character at index 6 (r) was excluded.

Also notice that language preserved its value. The slicing does not affect the original string. It just creates a brand new one representing the sliced substring.


If you omit the endIndex, the slice() extracts to the end of the string:

val language = "JavaScript"
val substring = language.substring(4)

println(substring) // Output: "Script"

Assignment
Follow the Coding Tutorial and let's slice some strings!


Hint
Look at the examples above if you get stuck.


STEP 1 OF 3
    Ctrl + Enter to check

    KOTLIN · STRINGS I

    String Slicing in Kotlin, explained

    What slicing is

    Slicing means cutting a run of consecutive characters out of a string. In Kotlin the basic tool is substring(startIndex, endIndex). It returns a new string made of the characters from startIndex up to, but not including, endIndex. Both indexes are zero-based, like the indexes you use to read a single character.

    val language = "JavaScript"
    val piece = language.substring(2, 6)
    
    println(piece)    // vaSc
    println(language) // JavaScript
    

    The character at index 2 is v and it is included. The character at index 6 is r and it is not. The result has endIndex - startIndex characters, here 4, which makes it easy to check your arithmetic.

    The original string is untouched. Kotlin strings are immutable, so substring always builds a new String and leaves the old one as it was.

    Leaving out the end index

    When you pass only the start index, the slice runs to the end of the string:

    val language = "JavaScript"
    println(language.substring(4)) // Script
    

    This form is the natural choice for "everything from here on". Combined with length, it also takes characters from the end: text.substring(text.length - 5) is the last five characters.

    The half-open range

    The start is included and the end is excluded. This is called a half-open range, and it has two useful properties:

    • The length of the slice is endIndex - startIndex, with no plus or minus one to remember.
    • Slices fit together. substring(0, 6) and substring(6) cover the string exactly, with no gap and no overlap.

    An empty slice is allowed: "Coding".substring(3, 3) is an empty string.

    The exercise

    The lesson gives a variable message and asks for three slices. Count the characters of "Coding feels great" first:

    • indexes 0 to 5 are Coding;
    • index 6 is a space;
    • indexes 7 to 11 are feels;
    • index 12 is a space;
    • indexes 13 to 17 are great.

    Now each step in turn:

    1. The first 6 characters. They sit at indexes 0 to 5, so the end index is 6, one past the last character you want.
    2. The 8th through 12th characters. People count from 1, Kotlin counts from 0, so these are indexes 7 to 11. The end index is 12.
    3. The last 5 characters. They start at index 13 and run to the end, so the one-argument form is enough.
    val message = "Coding feels great"
    
    val firstWord = message.substring(0, 6)
    val middleWord = message.substring(7, 12)
    val lastWord = message.substring(13)
    

    Each variable is declared with val because it is assigned once and never changes. Printing them gives:

    Coding
    feels
    great
    

    Other ways to slice

    Kotlin's standard library has shorter helpers for the common cases:

    val language = "JavaScript"
    
    println(language.take(4))     // Java
    println(language.takeLast(6)) // Script
    println(language.drop(4))     // Script
    println(language.substring(2..5)) // vaSc
    

    take(n) keeps the first n characters and drop(n) removes them. takeLast(n) keeps the last n. A range such as 2..5 is inclusive at both ends, so substring(2..5) is the same slice as substring(2, 6). The helpers do not throw when n is larger than the string: "abc".take(10) is just "abc".

    Common mistakes

    • Off-by-one on the end index. Writing substring(0, 5) for the first six characters loses the last one. The end index is the position after the slice.
    • Counting from 1. The "8th character" is at index 7.
    • Going out of bounds. An end index larger than the length, a start index larger than the length, or a start larger than the end all throw a StringIndexOutOfBoundsException. For "JavaScript", which has 10 characters, substring(4, 20) fails with Range [4, 20) out of bounds for length 10.
    • Forgetting to keep the result. message.substring(0, 6) on its own line produces a string that nobody uses. Store it in a variable or print it.
    • Expecting the original to change. After slicing, message still holds the whole text.

    Key takeaways

    • substring(start, end) includes start and excludes end.
    • substring(start) runs to the end of the string.
    • The slice length is end - start.
    • Slicing returns a new string; the original never changes.
    • Indexes outside 0..length throw an exception.
    Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free