Replacing text
The replace method swaps every occurrence of one piece of text for another and returns the result as a new string:
val sentence = "I love cats"
val result = sentence.replace("cats", "dogs")
println(result) // I love dogs
println(sentence) // I love cats
The original is unchanged because strings are immutable. Whatever replace returns is the only place the new text exists, so store it in a value or use it right away.
All occurrences, not just the first
println("aaa".replace("a", "b")) // bbb
println("banana".replace('a', 'o')) // bonono
println("abc".replace("x", "y")) // abc
A missing match isn't an error: you get the same text back. replace accepts two strings or two Char values, such as 'a' and 'o'.
The exercise, step by step
The lesson gives you val sentence = "I love cats".
- Call
replaceonsentencewith the text to find,"cats", and the text to put there,"dogs". - Store the result in a new
valnamedresult. It holdsI love dogs.
val sentence = "I love cats"
val result = sentence.replace("cats", "dogs")
replace versus replaceAll and replaceFirst
These three look alike but treat their first argument differently:
replace(old, new)takes plain text. Every character inoldmeans itself.replaceAll(regex, new)takes a regular expression and replaces every match.replaceFirst(regex, new)takes a regular expression and replaces only the first match.
The difference matters with characters that are special in a regular expression, such as the dot:
println("a.b.c".replace(".", "-")) // a-b-c
println("a.b.c".replaceAll(".", "-")) // -----
println("a1b22c".replaceAll("[0-9]+", "#")) // a#b#c
println("banana".replaceFirst("a", "o")) // bonana
In a regular expression the dot matches any character, so replaceAll(".", "-") turns every character into a dash. Use replace whenever you mean literal text.
Gotchas
- Ignoring the result. A line that is only
sentence.replace("cats", "dogs")does nothing useful. - Case matters.
"I love Cats".replace("cats", "dogs")changes nothing. - Deleting text. Replace with an empty string:
"a-b-c".replace("-", "")givesabc. - Chaining. Each call returns a string, so calls chain:
"a-b-c".replace("-", "").replace("a", "z")giveszbc. - Empty search text.
"abc".replace("", "-")inserts the replacement between every character and at both ends, giving-a-b-c-.
Replacing with something computed
The replacement doesn't have to be a literal. Any expression that produces a string works, so you can build the new text from other values:
val pet = "dogs"
val sentence = "I love cats"
println(sentence.replace("cats", pet)) // I love dogs
println(sentence.replace("cats", pet.toUpperCase)) // I love DOGS
This is useful for simple templates, such as replacing a placeholder word in a message. Keep in mind that the search is still literal and case-sensitive. If the placeholder might appear in different cases, convert the text first, but note that this changes the case of the whole string.
The exercise needs only one call, but chains of replace are common for cleaning text, such as turning every dash and underscore into a space.
Checking the result
For the lesson, result should differ from sentence: it is I love dogs while sentence still reads I love cats. If both print the same text, either the search text didn't match exactly, for example because of a different case or an extra space, or the returned string was thrown away instead of stored.
The two lengths also tell you something: cats and dogs have four letters each, so both strings have 11 characters. When the replacement is longer or shorter than the original text, the new string's length changes accordingly.
Key takeaways
s.replace(old, new)replaces all literal occurrences and returns a new string.replaceAllandreplaceFirstuse regular expressions.- The original string is never modified.
