Is there a means to get the index of the first non-whitespace character in a string (or more generally, the index of the first character matching a condition) in C# without
There is a very simple solution
string test = " hello world";
int pos = test.ToList<char>().FindIndex(x => char.IsWhiteSpace(x) == false);
pos will be 4
you can have more complex conditions like:
pos = test.ToList<char>().FindIndex((x) =>
{
if (x == 's') //Your complex conditions go here
return true;
else
return false;
}
);
You can use the String.IndexOfAny function which returns the first occurrence any character in a specified array of Unicode characters.
Alternatively, you can use the String.TrimStart function which remove all white space characters from the beginning of the string. The index of the first non-white space character is the difference between the length of the original string and the trimmed one.
You can even pick a set of characters to trim :)
Basically, if you are looking for a limited set of chars (let's say digits) you should go with the first method.
If you are trying to ignore a limited set of characters (like white spaces) you should go with the second method.
A Last method would be to use the Linq methods:
string s = " qsdmlkqmlsdkm";
Console.WriteLine(s.TrimStart());
Console.WriteLine(s.Length - s.TrimStart().Length);
Console.WriteLine(s.FirstOrDefault(c => !Char.IsWhiteSpace(c)));
Console.WriteLine(s.IndexOf(s.FirstOrDefault(c => !Char.IsWhiteSpace(c))));
Output:
qsdmlkqmlsdkm
8
q
8
Since there were several solutions here I decided to do some performance tests to see how each performs. Decided to share these results for those interested...
int iterations = 1000000;
int result = 0;
string s= " \t Test";
System.Diagnostics.Stopwatch watch = new Stopwatch();
// Convert to char array and use FindIndex
watch.Start();
for (int i = 0; i < iterations; i++)
result = Array.FindIndex(s.ToCharArray(), x => !char.IsWhiteSpace(x));
watch.Stop();
Console.WriteLine("Convert to char array and use FindIndex: " + watch.ElapsedMilliseconds);
// Trim spaces and get index of first character
watch.Restart();
for (int i = 0; i < iterations; i++)
result = s.IndexOf(s.TrimStart().Substring(0,1));
watch.Stop();
Console.WriteLine("Trim spaces and get index of first character: " + watch.ElapsedMilliseconds);
// Use extension method
watch.Restart();
for (int i = 0; i < iterations; i++)
result = s.IndexOf<char>(c => !char.IsWhiteSpace(c));
watch.Stop();
Console.WriteLine("Use extension method: " + watch.ElapsedMilliseconds);
// Loop
watch.Restart();
for (int i = 0; i < iterations; i++)
{
result = 0;
foreach (char c in s)
{
if (!char.IsWhiteSpace(c))
break;
result++;
}
}
watch.Stop();
Console.WriteLine("Loop: " + watch.ElapsedMilliseconds);
Results are in milliseconds....
Where s = " \t Test"
Convert to char array and use FindIndex: 154
Trim spaces and get index of first character: 189
Use extension method: 234
Loop: 146
Where s = "Test"
Convert to char array and use FindIndex: 39
Trim spaces and get index of first character: 155
Use extension method: 57
Loop: 15
Where s = (1000 character string with no spaces)
Convert to char array and use FindIndex: 506
Trim spaces and get index of first character: 534
Use extension method: 51
Loop: 15
Where s = (1000 character string that starts with " \t Test")
Convert to char array and use FindIndex: 609
Trim spaces and get index of first character: 1103
Use extension method: 226
Loop: 146
Draw your own conclusions but my conclusion is to use whichever one you like best because the performance differences is insignificant in real world scenerios.
Yes you can try this:
string stg = " xyz";
int indx = (stg.Length - stg.Trim().Length);
You can trim, get the first character and use IndexOf.