I need to be able to say something like myString.IndexOf(c => !Char.IsDigit(c))
, but I can't find any such method in the .NET framework. Did I miss something?
The following works, but rolling my own seems a little tedious here:
using System;
class Program
{
static void Main()
{
string text = "555ttt555";
int nonDigitIndex = text.IndexOf(c => !Char.IsDigit(c));
Console.WriteLine(nonDigitIndex);
}
}
static class StringExtensions
{
public static int IndexOf(this string self, Predicate<char> predicate)
{
for (int index = 0; index < self.Length; ++index) {
if (predicate(self[index])) {
return index;
}
}
return -1;
}
}
IndexOf(string) has no options and Contains() uses an Ordinal compare (a byte-by-byte comparison rather than trying to perform a smart compare, for example, e with é). So IndexOf will be marginally faster (in theory) as IndexOf goes straight to a string search using FindNLSString from kernel32.
Definition and Usage The indexOf() method returns the position of the first occurrence of specified character(s) in a string. Tip: Use the lastIndexOf method to return the position of the last occurrence of specified character(s) in a string.
The indexOf() method returns the position of the first occurrence of a value in a string. The indexOf() method returns -1 if the value is not found. The indexOf() method is case sensitive.
In C#, IndexOf() method is a string method. This method is used to find the zero-based index of the first occurrence of a specified character or string within the current instance of the string. The method returns -1 if the character or string is not found.
Your current solution is better but could do something like ...
int c = myString.TakeWhile(c => Char.IsDigit(c)).Count();
return (c == myString.Length) ? -1 : c;
Slightly shorter and somewhat fewer exception cases than the other proposals here, edited to show how to handle -1 case. Note that the predicate is the inverse of the predicate in the question because we want to count how many characters ARE digits before we find a non-digit.
You're not missing anything. There is no IndexOf
in the manner you're searching for in the framework. The closest thing you could do without rolling your own would be
text
.Select((c, index) => new { Char = c, Index = index })
.Where(pair => !Char.IsDigit(pair.Char))
.Select(pair => pair.Index)
.FirstOrDefault(-1);
However that is not easy to follow and causes senseless allocations. I'd much prefer to roll my own IndexOf
in this case.
EDIT Whoops. Forgot that FirstOrDefault
is a function I have hand rolled in my apps and is not a part of the standard LINQ libraries with this overload.
public static T FirstOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) {
using (var enumerator = enmumerable.GetEnumerator()) {
if (enumerator.MoveNext()) {
return enumerator.Current;
}
return defaultValue;
}
Here is a version that works without any custom extensions. Note this is for example only, please don't put this in your app ;)
text
.Select((c, index) => new { Char = c, Index = index })
.Where(pair => !Char.IsDigit(pair.Char))
.Select(pair => pair.Index)
.Concat(Enumerable.Repeat(-1, 1))
.First();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With