是否有一个带谓词的String.IndexOf?

时间:2011-09-14 17:40:34

标签: 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 => !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;
    }
}

5 个答案:

答案 0 :(得分:4)

你没有遗漏任何东西。您在框架中搜索的方式没有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;
}

这是一个没有任何自定义扩展程序的版本。请注意,这仅作为示例,请不要将其放在您的应用中;)

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();

答案 1 :(得分:2)

您当前的解决方案更好,但可以做类似的事情......

int c = myString.TakeWhile(c => Char.IsDigit(c)).Count();
return (c == myString.Length) ? -1 : c;

比这里的其他提案略短且少一些例外情况,编辑以显示如何处理-1案例。请注意,谓词是问题中谓词的倒数,因为我们想要在找到非数字之前计算ARE数字的位数。

答案 2 :(得分:1)

MSDN将向您展示给定类型的所有方法和扩展:MSDN String Class

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

编辑我错误地认为使用RegEx查找索引的效率......

答案 3 :(得分:0)

Array.FindIndex()提供谓词重载,但仅适用于char []。所以你可以将你的字符串转换为char数组并使用像这样的Array.FindIndex:

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

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

答案 4 :(得分:0)

由于 IEnumerable<char> 是一个 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; } ,您可以很容易地概括您的扩展方法以支持几乎任何类型的集合(包括字符串):

public interface FirebaseInterfaceInCore {
    public void sendMessage(String mesaj);
}