C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
It has XYZ but we want ABC. Replace helps with this puzzle. It swaps those substrings.
In programs, every replacement made results in a new string. Unneeded Replace calls should be removed. Replace changes all occurrences. It handles char replacements.
A simple example. To begin, we invoke the Replace method. Please note that we must assign Replace's result to a variable. It does not modify the string in-place.
Here: We introduce a const string literal. We call Replace() on this character data, and it returns a new string object.
WriteLine: We pass the "output" string to Console.WriteLine to print it to the console window.
Based on: .NET 4.5 C# program that uses Replace using System; class Program { static void Main() { const string input = "_::_pagitica"; Console.WriteLine(input); // Call Replace on the string. // ... We must assign the result of the Replace call. string output = input.Replace("_::_", "Areo"); Console.WriteLine(output); } } Output _::_pagitica Areopagitica
Every instance. This is important. The Replace method changes every instance of the specified substring. This can sometimes result in unexpected behavior. The first match is not targeted.
Here: To demonstrate, the console program replaces the word "Net" with the word "Basket." There is no need to call Replace two times.
Note: A second Replace() would not do anything. It would just result in CPU cycles being wasted.
C# program that causes multiple replacements using System; class Program { static void Main() { const string s = "Dot Net Perls is about Dot Net."; Console.WriteLine(s); // We must assign the result to a variable. // ... Every instance is replaced. string v = s.Replace("Net", "Basket"); Console.WriteLine(v); } } Output Dot Net Perls is about Dot Net. Dot Basket Perls is about Dot Basket.
StringBuilder. This is an important type. With StringBuilder, Replace works the same way as with strings, but we don't need to assign the result to anything.
Here: In this example, we create a StringBuilder. We use the constructor to initialize the StringBuilder with a short sentence.
Replace: We replace the word "This" with the word "Here." The result has the new word in place of the old word.
C# program that uses StringBuilder using System; using System.Text; class Program { static void Main() { const string s = "This is an example."; // Create new StringBuilder from string. StringBuilder b = new StringBuilder(s); Console.WriteLine(b); // Replace the first word. // ... The result doesn't need assignment. b.Replace("This", "Here"); Console.WriteLine(b); // Insert the string at the beginning. b.Insert(0, "Sentence: "); Console.WriteLine(b); } } Output This is an example. Here is an example. Sentence: Here is an example.
Problem. Replace() creates a string copy each time it is called. This can lead to measurable performance problems. MSDN notes that Replace returns a new string.
This method does not modify the value of the current instance. Instead, it returns a new string in which all occurrences of oldValue are replaced by newValue.
Rewrite. It is usually easy to rewrite wasteful string Replace code with StringBuilder. Here I show the original code that uses string and then the new StringBuilder code.
Version A: This version ends up creating many string copies. It replaces whitespace around punctuation.
Version B: MinifyB is similar but uses StringBuilder. It does the same replacements as version A.
String Replace example: C# /// <summary> /// A - Eliminates extra whitespace. /// </summary> static string MinifyA(string p) { p = p.Replace(" ", string.Empty); p = p.Replace(Environment.NewLine, string.Empty); p = p.Replace("\\t", string.Empty); p = p.Replace(" {", "{"); p = p.Replace(" :", ":"); p = p.Replace(": ", ":"); p = p.Replace(", ", ","); p = p.Replace("; ", ";"); p = p.Replace(";}", "}"); return p; } StringBuilder Replace example: C# /// <summary> /// B - Eliminates extra whitespace. /// </summary> static string MinifyB(string p) { StringBuilder b = new StringBuilder(p); b.Replace(" ", string.Empty); b.Replace(Environment.NewLine, string.Empty); b.Replace("\\t", string.Empty); b.Replace(" {", "{"); b.Replace(" :", ":"); b.Replace(": ", ":"); b.Replace(", ", ","); b.Replace("; ", ";"); b.Replace(";}", "}"); return b.ToString(); }
Benchmark. We next see if there is a difference between version A and B above. The version that avoids copies, with StringBuilder, is many times faster.
Tip: Neither method is close to optimal, as internally each call to Replace must search the string.
Tip 2: This benchmark does demonstrate a clear advantage of StringBuilder. It does not show how to write a good CSS minify method.
Replace methods benchmark, 20 chars Method A - String Replace: 5.60 seconds Method B - StringBuilder Replace: 0.62 seconds [faster] Replace methods benchmark, 1000 chars Method A - String Replace: 21.80 seconds Method B - StringBuilder Replace 4.89 seconds [faster]
Argument performance. Here we test a program that calls Replace in four ways. The first two calls use char arguments. The second two calls use string arguments.
Note: Only the second and the fourth calls require that the string be changed in memory.
Tip: Avoiding an object allocation has a performance benefit. And often this outweighs any extra CPU usage.
Result: Replace calls that use chars are faster. And if no change occurs, Replace will return faster.
C# program that benchmarks Replace using System; using System.Diagnostics; class Program { const int _max = 1000000; static void Main() { string test = "TheDeveloperBlog"; var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace('x', 'y'); } s1.Stop(); var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace('d', 'y'); } s2.Stop(); var s3 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace("x", "y"); } s3.Stop(); var s4 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace("d", "y"); } s4.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s4.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.Read(); } } Output 13.00 ns Char Replace, no change 47.75 ns Char Replace, change 73.26 ns String Replace, no change 117.07 ns String Replace, change
Logic optimization. Replace can be optimized. Suppose in our program many string replacements must be done. But often nothing is changed in actual strings.
Version A: Let's look at the initial version of the method. It runs four Replace calls on the formal parameter to the method.
Version B: The second version uses the Contains method around all the Replace calls with the specified common string literal.
Tip: In version B, the first two Replace calls are only run when the common pattern is found. Often the string is searched less.
First version of method: C# static string A(string text) { text = text.Replace("<span>Cat ", "<span>Cats "); text = text.Replace("<span>Clear ", "<span>Clears "); text = text.Replace("<span>Dog ", "<span>Dogs "); text = text.Replace("<span>Draw ", "<span>Draws "); return text; } Second version of method: C# static string B(string text) { if (text.Contains("<span>C")) { text = text.Replace("<span>Cat ", "<span>Cats "); text = text.Replace("<span>Clear ", "<span>Clears "); } if (text.Contains("<span>D")) { text = text.Replace("<span>Dog ", "<span>Dogs "); text = text.Replace("<span>Draw ", "<span>Draws "); } return text; }
Split. Often strings contains invalid syntax. We can use Replace to fix incorrect parts of a string before using Split to separate it.
Whitespace. We often need to remove or change whitespace in strings, particularly those read in from files. We can handle tabs, spaces and line breaks.
A summary. As strings are immutable, Replace does not modify them. It instead creates a new copy with the replacements applied. It replaces all instances of a match.
For frequent replacement, StringBuilder is much faster. It avoids copies. Other than implementation, the methods are used in a similar way, with the same arguments.