C# 该类型第n个字符的索引

C# 该类型第n个字符的索引,c#,indexof,C#,Indexof,我需要获取字符串中该类型的第n个字符的索引 例如: string test = "asdfasdfasdf"; int index = test.IndexOf("a", 3); 而索引将是8,因为第三个a的索引是8 有一个函数可以这样做吗?或者你知道如何以一种智能的方式这样做吗?一个简单的for循环就可以做到这一点,但是你可以将for循环放在一个扩展方法中以在整个应用程序中将此功能作为一行程序 像这样: public static int NthIndexOf(this string tex

我需要获取字符串中该类型的第n个字符的索引

例如:

string test = "asdfasdfasdf";
int index = test.IndexOf("a", 3);
索引将是8,因为第三个a的索引是8


有一个函数可以这样做吗?或者你知道如何以一种智能的方式这样做吗?

一个简单的for循环就可以做到这一点,但是你可以将for循环放在一个扩展方法中以在整个应用程序中将此功能作为一行程序

像这样:

public static int NthIndexOf(this string text, char letter, int occurrence)
{
    if (text == null) throw new ArgumentNullException(nameof(text));

    int count = 0;
    for (int index = 0; index < text.Length; index++)
        if (text[index] == letter)
        {
            if (++count == occurrence)
                return index;
        }
    return -1;
}

您可以在一行中完成,但它并不漂亮:

var s = "aabbabhjhjdsfbaxt";
var idx = s.Select((c, i) => new {c, i})
    .Where(p => p.c == 'a')
    .Skip(2)
    .FirstOrDefault()?.i ?? -1;
其思想是将字符与其索引配对,按字符过滤,跳过n-1项,如果存在下一项,则采用下一项

另一种方法是使用带有look-behind的正则表达式:

var idx = Regex.Match(s, "(?<=(a[^a]*){2})a").Index;

var idx=Regex.Match,”(?您可以为此创建一个扩展方法,如下所示:

public static int NthIndexOf(this string s, char c, int occurence)
{
    if (s == null) throw new ArgumentNullException(nameof(s));
    if (occurence <= 0) return -1;

    int i = -1, o = 0;
    do
    {
        i = s.IndexOf(c, i+1);
        o++;
    } while (i >= 0 && o < occurence);

    return i;
}


当然,您可以对
c
使用
string
类型的参数,而不是
char
,但需要将
s.IndexOf(c,i+1)
更改为
s.IndexOf(c,i+c.Length)

,正如Rene Vogt所说的,您应该使用扩展方法将调用链接到
IndexOf()
出于性能原因:

public static int NthIndexOf(this string s, string value, int n)
{
    var index = -1;

    for (; n > 0; n--)
        index = s.IndexOf(value, index + 1);

    return index;
}
这将返回字符串
值出现时(基于1的)
n
的从0开始的索引


这里有一个工作示例:

您可以在几行代码中使用一个计数器和一个for循环来完成它。@itsme86是的,我可能可以,但我要问的是是否有一行代码来完成它。基本上只是curiosity@itsme86好的,谢谢。您必须为该方法使用一个不同的名称作为带有该签名的重载。@lenny,那么您认为如何当你告诉它开始一个位置
3
时,
索引将成为
8
,这将产生
4
,甚至不运行代码..来吧..我会使用
.FirstOrDefault()?.I???-1
索引()对齐
@GoodNightnerdPred这是一个很好的主意,非常感谢!哦,我多么喜欢与linq一起玩,创建如此有趣的小查询..但考虑到内存使用和性能,特别是字符串操作,我认为这绝对是一个非常糟糕的解决方案。我不知道OP需要它做什么,但因为它如果(希望)被包装到一个扩展中,无论如何,人们应该坚持使用简单的循环或现有的字符串操作(例如concat
IndexOf('a',i)
调用)。@RenéVogt我同意——引用Dijkstra的话,“我不喜欢(用大锤敲打鸡蛋),不管大锤敲打鸡蛋有多有效。“第一个解决方案不过是演示如何用一把闪亮的新LINQ大锤来实现这一点,而不是在生产中应该做的事情。你能通过添加一些代码来完成答案吗?这是一个非常好的解决方案。
while(){}
do{}while()之间的区别是什么?”
loop?@lenny区别在于
while
在循环体之前测试条件,而
do-while
在循环体的末尾测试条件。由于我需要初始化
I
但测试
IndexOf
的结果,我选择
do-while
,因为它在第一次调用之后测试
I
e> IndexOf
,而不是在此之前。
string test = "asdfasdfasdf";
int index = test.NthIndexOf('a', 3); // 8
public static int NthIndexOf(this string s, string value, int n)
{
    var index = -1;

    for (; n > 0; n--)
        index = s.IndexOf(value, index + 1);

    return index;
}