C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Argument 1: The starting index of the substring. Please remember strings are indexed with the first character 0.
Argument 2: The length of the substring part. This is not the final index, but the count of characters in the substring we want.
String LengthC# program that uses Substring
using System;
class Program
{
static void Main()
{
string input = "OneTwoThree";
// Get first three characters.
string sub = input.Substring(0, 3);
Console.WriteLine("Substring: {0}", sub);
}
}
Output
Substring: One
Substring parameters
Substring(0, 3) Returns substring of first 3 chars.
Substring(3, 3) Returns substring of second 3 chars.
Substring(6) Returns substring of all chars after first 6.
Here: The program describes logic that takes all the characters in the input string excluding the first 3.
Result: We extract the last several characters from the string. The length is reduced by 3.
C# program that calls Substring, one argument
using System;
class Program
{
static void Main()
{
string input = "OneTwoThree";
// Indexes:
// 0:'O'
// 1:'n'
// 2:'e'
// 3:'T'
// 4:'w' ...
string sub = input.Substring(3);
Console.WriteLine("Substring: {0}", sub);
}
}
Output
Substring: TwoThree
Note: We will want each argument to be a non-zero value to avoid the edge characters. Be careful to validate arguments.
Parameters: In this example, the two parameters say, "I want the substring at index 3 with a length of three."
C# program that uses Substring, two arguments
using System;
class Program
{
static void Main()
{
string input = "OneTwoThree";
string sub = input.Substring(3, 3);
Console.WriteLine("Substring: {0}", sub);
}
}
Output
Substring: Two
Info: This method reduces the length of a string. It will cause an error if the string is too short—a check would be needed.
Remove: The Remove method can be used to remove parts of strings too. It just internally forwards to Substring with the correct arguments.
RemoveC# program that uses Substring, ending characters
using System;
class Program
{
static void Main()
{
string input = "OneTwoThree";
string sub = input.Substring(0, input.Length - 5);
Console.WriteLine("Substring: {0}", sub);
}
}
Output
Substring: OneTwo
Part 1: We call IndexOf to locate the position of the separator in the string. If found, the returned value is never -1.
IndexOfPart 2: If the separator is found, we call Substring to get the following part. We add the separator's length to the start index.
C# program that uses IndexOf with Substring
using System;
class Program
{
static void Main()
{
string value = "Unit: 300 V";
string separator = ": ";
// Part 1: get index of separator.
int separatorIndex = value.IndexOf(separator);
// Part 2: if separator exists, get substring.
if (separatorIndex >= 0)
{
string result = value.Substring(separatorIndex + separator.Length);
Console.WriteLine("RESULT: {0}", result);
}
}
}
Output
RESULT: 300 V
Part A: Here we try to get a substring with a negative starting index—this makes no sense, and causes an error.
Part B: We cannot take a Substring with a length past the end of the source string. This causes an ArgumentOutOfRangeException.
ArgumentExceptionC# program that shows exceptions
using System;
class Program
{
static void Main()
{
string input = "OneTwoThree";
// Part A: try negative start index.
try
{
string sub = input.Substring(-1);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
// Part B: try excessive length.
try
{
string sub = input.Substring(0, 100);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
Output
System.ArgumentOutOfRangeException
System.String.InternalSubStringWithChecks
System.ArgumentOutOfRangeException
System.String.InternalSubStringWithChecks
Info: We can use string.IsNullOrEmpty to prevent a NullReferenceException. This also checks for an empty string.
IsNullOrEmpty, IsNullOrWhiteSpaceC# program that causes NullReferenceException
using System;
class Program
{
static void Main()
{
string value = null;
// This is safe.
if (!string.IsNullOrEmpty(value))
{
Console.WriteLine(value.Substring(1));
}
// This will cause an exception.
Console.WriteLine(value.Substring(1));
}
}
Output
Unhandled Exception: System.NullReferenceException:
Object reference not set to an instance of an object.
Note: Substring creates an object on the heap. The string indexer just returns a char, which is an integer-like value—this is faster.
CharC# program that uses char, Substring
using System;
class Program
{
static void Main()
{
string value = "cat";
// ... In many programs, we can use a char instead of Substring.
Console.WriteLine(value[0]);
Console.WriteLine(value.Substring(0, 1));
}
}
Output
c
c
Here: I introduce simple code in SubstringFirst3 that optimizes the case of getting the first 3 letters of the string "Windows."
So: In a program that happens to do this operation many times, this logic would reduce allocations and increase speed.
C# program that avoids Substring
using System;
class Program
{
static string SubstringFirst3(string value)
{
// ... Use logic to avoid creating a new string.
if (value == "Windows")
{
return "Win";
}
else
{
return value.Substring(0, 3);
}
}
static void Main()
{
Console.WriteLine(SubstringFirst3("Windows"));
Console.WriteLine(SubstringFirst3("Computer"));
}
}
Output
Win
Com
And: This approach can be many times faster than using IndexOf, but only works in certain cases.
Dictionary: If we were to place these substrings in a Dictionary, use the substring for the key, and the original string for the value.
DictionaryImportant: Do not attempt this on a long string, or memory usage might explode. A tree data structure can be an even better solution.
Here: We generate all substrings for an input string. These substrings can be used as keys in a Dictionary.
C# program that generates all substrings
using System;
class Program
{
static void Main()
{
string value = "abcdefghi";
// Avoid full length.
for (int length = 1; length < value.Length; length++)
{
// Be careful with the end index.
for (int start = 0; start <= value.Length - length; start++)
{
string substring = value.Substring(start, length);
Console.WriteLine(substring);
}
}
}
}
Output
a
b
c
d
e
f
g
h
i
ab
bc
cd
de
ef
fg
gh
hi
abc
bcd
cde
def
efg
fgh
ghi
abcd
bcde
cdef
defg
efgh
fghi
abcde
bcdef
cdefg
defgh
efghi
abcdef
bcdefg
cdefgh
defghi
abcdefg
bcdefgh
cdefghi
abcdefgh
bcdefghi
Version 1: This code creates a char array and assigns elements from the source string. Then it creates a string with a constructor.
Version 2: This version uses the Substring() method—it is shorter, simpler, and faster.
Result: Substring is faster. But if we want to extract only certain characters, consider the char array approach shown.
Char ArrayTip: It is best to use Substring when it has equivalent behavior. Code is shorter, simpler and easier to read.
C# program that benchmarks new string from char array
using System;
using System.Diagnostics;
class Program
{
const int _max = 1000000;
static void Main()
{
const string value = "onetwothree";
// Version 1: create new string from char array.
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
char[] array = new char[3];
array[0] = value[3];
array[1] = value[4];
array[2] = value[5];
string result = new string(array);
if (result == null)
{
return;
}
}
s1.Stop();
// Version 2: use Substring.
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
string result = value.Substring(3, 3);
if (result == null)
{
return;
}
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
}
}
Output
19.19 ns new char[], new string()
13.58 ns Substring
Version 1: This code uses a 1-char substring call to get the first letter of the word "jounce."
Version 2: This version accesses the first character with an index expression. It performs faster.
Result: If your program creates 1-char substrings occasionally, it might be worth special-casing those calls to access a char instead.
C# program that tests one-char substring performance
using System;
using System.Diagnostics;
class Program
{
const int _max = 1000000;
static void Main()
{
const string value = "jounce";
// Version 1: get 1-character substring.
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
string firstLetter = value.Substring(0, 1);
if (firstLetter != "j")
{
return;
}
}
s1.Stop();
// Version 2: access char directly.
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
char firstLetter = value[0];
if (firstLetter != 'j')
{
return;
}
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
}
}
Output
18.07 ns Substring, 1-char
0.99 ns Access char directly
Slice: In Python and JavaScript, slice notation is often used. We can use relative indexes.
Quote: Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
String.Substring Method: Microsoft DocsSometimes: We only need a single part of a large string. If we avoid Split in this case, we can avoid creating many strings.
Bugs: This style of optimization can yield code that is fast but prone to bugs. Be prepared to fix problems.