IndexOf
From the start to the end, the IndexOf
method in C# searches one string
for another. It returns the index of the string
part, if one is found.
If the substring or char
is not found, IndexOf
returns -1. If we test for positive values, we can tell if the value was present.
We use IndexOf
to see if a string
contains a word. Usually we want to know the exact result of IndexOf
. We can store its result in an int
local.
IndexOf
returns the location of the string
"dog." It is located at index 4.IndexOf
against the special constant -1. The string
"turnip" is not found, so we get -1.using System; string value = "cat,dog"; // Part 1: find index of dog. Console.WriteLine(value.IndexOf("dog")); // Part 2: test not found value. if (value.IndexOf("turnip") == -1) { Console.WriteLine("?"); }4 ?
We often use IndexOf
in loops. We have to keep track of several values at once. This prevents us from searching the same parts over and over again.
IndexOf
here is the character we are searching for—in this case the lowercase letter "a."string
. With the initial value 0, we begin at the first char
.using System; // The input string. string s = "I have a cat"; // Loop through all instances of the letter a. int i = 0; while ((i = s.IndexOf('a', i)) != -1) { // Print out the substring. Console.WriteLine(s.Substring(i)); // Increment the index. i++; }ave a cat a cat at
This is -1 when IndexOf
does not find anything, and the index if it does. Often an IndexOutOfRangeException
can provoked by using the -1 in other code (like an array access).
IndexOf
. It is probably better to check for negative one at least once in most places.using System; string source = "big dog"; // See result of IndexOf method. Console.WriteLine("NOT FOUND: {0}", source.IndexOf("cat")); Console.WriteLine("FOUND: {0}", source.IndexOf("dog"));NOT FOUND: -1 FOUND: 4
Substring
We can use IndexOf
with the Substring
method. Here we get the first substring that begins with a certain pattern or character.
Substring
method returns the rest of the string
starting at a specified number.using System; // Input. const string s = "I have a cat"; // Location of the letter c. int i = s.IndexOf('c'); // Remainder of string starting at c. string d = s.Substring(i); Console.WriteLine(d);cat
Skip
startOften strings have leading characters that we know cannot contain the searched-for value. We can skip these chars. This will give a performance boost—less searching is needed.
using System; string value = ":100,200"; // Skip the first character with a startIndex of 1. int comma = value.IndexOf(',', 1); Console.WriteLine(comma);4
IndexOfAny
This method receives a char
array argument. It searches for the first index of any of the characters provided in that array.
IndexOf
several times with the logical "or" operator.IndexOfAny
has different performance characteristics. It may result in clearer code.using System; var code = "xyz"; // Use IndexOfAny to find an "a" or "z". int result = code.IndexOfAny(new char[] { 'a', 'z' }); if (result != -1) { Console.WriteLine("a or z found at {0}", result); }a or z found at 2
LastIndexOf
This works like IndexOf
, but searches in reverse, from the right to the left part of the string
. It starts with the last char
.
char
in the string. We find one at index 7, even though an earlier one occurs in the source string
.LastIndexOfAny
searches in reverse, and tests the character array for any match.using System; var code = "cat_dog_?"; // Find last underscore. int result = code.LastIndexOf('_'); if (result != -1) { Console.WriteLine("_ found at {0}", result); }_ found at 7
Contains
This is a wrapper method. It calls IndexOf
with StringComparison.Ordinal
. It returns true or false, not an integer—so it is a bit simpler to use.
Contains
internal IndexOf
returns -1 contains returns false. Otherwise it returns true.using System; var name = "red paint"; // Use Contains to see if a string is found in a source string. if (name.Contains("paint")) { Console.WriteLine("paint found!"); }paint found!
for
-loopShould we prefer IndexOf
over for
-loops when
-possible? Scanning a string
is a common operation. Choosing the fastest code here could help many programs.
for
-loop. We see the "for" and "if" keywords in the code.IndexOf()
method with a single char
argument to search a string
.IndexOf
.IndexOf
is more complex—it is harder to optimize for the compiler.using System; using System.Diagnostics; const int _max = 1000000; string s = "abc.123.456.xyz"; // Version 1: use for-loop to count chars. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { int c = 0; for (int e = 0; e < s.Length; e++) { if (s[e] == '.') { c++; } } } s1.Stop(); // Version 2: use IndexOf to count chars. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { int c = 0; int e = 0; while ((e = s.IndexOf('.', e)) != -1) { e++; c++; } } s2.Stop(); // Result times. Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns"));18.21 ns: For-loop 26.78 ns: IndexOf, while-loop
char
argumentSometimes we are searching for a single character. We can specify this single character as a 1-char string
, or a char
.
IndexOf
with a char
argument. We use a char
instead of a string
, but the output is the same.IndexOf
with a single-character string
argument.string
IndexOf
will require more CPU cycles. And even if we pass in StringComparison.Ordinal
, it is slower.char
argument is more efficient. Using a string
is many times slower than using a char
value.using System; using System.Diagnostics; const int _max = 1000000; string value = "The puppy is adorable."; // Version 1: use char argument. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { int result = value.IndexOf('a'); } s1.Stop(); // Version 2: use string argument. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { int result = value.IndexOf("a"); } s2.Stop(); // Result times. Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); 13.07 ns: IndexOf char argument 226.86 ns: IndexOf string argument
Array.IndexOf
We call IndexOf
on strings, but we can also use (different) IndexOf
methods on arrays and Lists. These also return -1 if nothing is found.
We commonly use IndexOf
to search for chars (or substrings) in strings. For complex problems, a for
-loop may be easier to write and faster to execute.