C# 是否存在接受谓词的String.IndexOf?

C# 是否存在接受谓词的String.IndexOf?,c#,.net,linq,C#,.net,Linq,我需要能够说一些类似于myString.IndexOf(c=>!Char.IsDigit(c)),但在.NET框架中找不到任何这样的方法。我错过什么了吗 以下是我的作品,但我自己的作品在这里似乎有点乏味: using System; class Program { static void Main() { string text = "555ttt555"; int nonDigitIndex = text.IndexOf(c => !Ch

我需要能够说一些类似于
myString.IndexOf(c=>!Char.IsDigit(c))
,但在.NET框架中找不到任何这样的方法。我错过什么了吗

以下是我的作品,但我自己的作品在这里似乎有点乏味:

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;
    }
}
使用系统;
班级计划
{
静态void Main()
{
字符串text=“555ttt555”;
int nonDigitIndex=text.IndexOf(c=>!Char.IsDigit(c));
控制台写入线(非数字索引);
}
}
静态类StringExtensions
{
公共静态int IndexOf(该字符串本身,谓词)
{
for(int index=0;index
MSDN将显示给定类型的所有方法和扩展:

目前还没有专门针对
String
的扩展方法来准确描述您提供的内容。正如其他人所说,滚动自己的不是一个坏的选择,因为其他选项(除了
regex
)没有那么优雅


Edit关于使用
RegEx
查找索引的效率,我错了…

你没有遗漏任何东西。您在框架中搜索的方式没有
IndexOf
。你能做的最接近你自己的事情是

text
  .Select((c, index) => new { Char = c, Index = index })
  .Where(pair => !Char.IsDigit(pair.Char))
  .Select(pair => pair.Index)
  .FirstOrDefault(-1);
然而,这并不容易遵循,并导致无意义的分配。在这种情况下,我更愿意使用自己的
IndexOf

编辑哎呀。忘记了
FirstOrDefault
是我在应用程序中手动推出的一个函数,并且不是具有此重载的标准LINQ库的一部分

public static T FirstOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) {
  using (var enumerator = enmumerable.GetEnumerator()) {
    if (enumerator.MoveNext()) {
      return enumerator.Current;
    }
    return defaultValue;
}

您当前的解决方案更好,但可以执行以下操作

int c = myString.TakeWhile(c => Char.IsDigit(c)).Count();
return (c == myString.Length) ? -1 : c;
与此处的其他建议相比,异常情况略短,也略少,经过编辑以显示如何处理-1情况。请注意,谓词与问题中的谓词相反,因为我们要在找到非数字之前计算数字字符的数量。

数组。FindIndex()提供谓词重载,但仅适用于char[]。因此,您可以将字符串转换为char数组并使用array.FindIndex,如下所示:

Array.FindIndex( text.ToCharArray(), 0, c => Char.IsDigit( c ) )

性能损失应该很小,因为字符串可能存储在char数组中。

由于
string
是一个
IEnumerable
,您可以很容易地推广扩展方法,以支持几乎任何类型的集合(包括字符串):

public static int IndexOf<T>(this IEnumerable<T> list, Predicate<T> predicate)
{
    var index = 0;
    foreach (var item in list)
    {
        if (predicate(item))
        {
            return index;
        }
        ++index;
    }
    return -1;
}
publicstaticintindexof(这个IEnumerable列表,谓词)
{
var指数=0;
foreach(列表中的变量项)
{
if(谓语(项))
{
收益指数;
}
++指数;
}
返回-1;
}

为什么不使用正则表达式?+1@Rune:当然比枚举一个字符串要快你已经滚动了它,繁琐的部分已经处理好了:)@IAbstract-huh?你认为正则表达式能做什么?正则表达式对于我想做的事情来说是多余的。+1 for:在这种情况下,我更愿意使用我自己的IndexOf。OPs的使用情况很好IMHO@IAbstract:+1代表你的+1。我喜欢他已有的扩展方法。我会把它扔进公用程序类的一个公共程序集中,并称之为“完成”…你是说我没有回答OPs问题:是否有一个String.IndexOf接受谓词?不-你在这个例子中是对的抱歉-我(和这里的其他人一样)只是把它当作“请给我看一个简短的版本”…如果字符不在那里,它将生成0。我看你已经更新了,但你可能真的应该处理这个问题。目前,无法区分“与谓词匹配的第一个字符位于字符串的索引0处”和“字符串中没有与谓词匹配的字符”。@dlev请注意,我的谓词与问题相反;它确实区分了这两种情况。如果字符串中没有与谓词匹配的字符,它将返回字符串的长度,或者现在,通过编辑它将返回-1。@antisanity:如果第一个字符是非数字,则
TakeWhile()
中的序列将为空,Count()将为0而不是1。虽然此代码段可能是解决方案,确实有助于提高你的文章质量。请记住,您将在将来回答读者的问题,这些人可能不知道您的代码建议的原因。
public static int IndexOf<T>(this IEnumerable<T> list, Predicate<T> predicate)
{
    var index = 0;
    foreach (var item in list)
    {
        if (predicate(item))
        {
            return index;
        }
        ++index;
    }
    return -1;
}