有字符串吗?接受谓词的IndexOf

本文关键字:谓词 IndexOf 字符串 | 更新日期: 2023-09-27 18:08:40

我需要能够说出类似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;
    }
}

有字符串吗?接受谓词的IndexOf

你不会错过任何东西。没有您在框架中搜索的方式的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();

你目前的解决方案是更好的,但是可以做一些像…

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

比这里的其他建议稍微短一些,并且稍微少一些异常情况,编辑以显示如何处理-1情况。注意,谓词与问题中的谓词相反,因为我们希望在找到非数字之前计算有多少字符是数字。

MSDN将显示给定类型的所有方法和扩展:MSDN字符串类

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

编辑我误解了使用RegEx查找索引的效率…

Array.FindIndex()提供谓词重载,但仅适用于char[]。你可以将字符串转换为字符数组并使用array。查找索引如下:

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

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

由于StringIEnumerable<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;
}