C#字符串中字符的第三个索引

时间:2011-01-02 14:16:24

标签: c# .net string indexing

是否有一个命令可以获取字符串中字符的第三个索引?例如:

error: file.ext: line 10: invalid command [test:)]

在上面的句子中,我想要第3个冒号的索引,10个旁边的那个。我怎么能这样做?我知道string.IndexOf和string.LastIndexOf,但在这种情况下我想得到第三次使用时字符的索引。

10 个答案:

答案 0 :(得分:13)

String.IndexOf会得到第一个索引,但是有重载给出起点。因此,您可以使用第一个IndexOf加1的结果作为下一个的起点。然后只是累积索引足够多次:

var offset = myString.IndexOf(':');
offset = myString.IndexOf(':', offset+1);
var result = myString.IndexOf(':', offset+1);

添加错误处理,除非您知道myString包含至少三个冒号。

答案 1 :(得分:9)

你可以这样写:

    public static int CustomIndexOf(this string source, char toFind, int position)
    {
        int index = -1;
        for (int i = 0; i < position; i++)
        {
            index = source.IndexOf(toFind, index + 1);

            if (index == -1)
                break;
        }

        return index;
    }

编辑:显然你必须按如下方式使用它:

int colonPosition = myString.CustomIndexOf(',', 3);

答案 2 :(得分:4)

我猜你想把那个字符串解析成不同的部分。

public static void Main() {
    var input = @"error: file.ext: line 10: invalid command [test (: ]";
    var splitted = input .Split(separator: new[] {": "}, count: 4, options: StringSplitOptions.None);

    var severity = splitted[0]; // "error"
    var filename = splitted[1]; // "file.ext"
    var line = splitted[2];     // "line 10"
    var message = splitted[3];  // "invalid command [test (: ]"
}

答案 3 :(得分:2)

已经有几种非常好的方法可以解决这个问题 - 但我决定尝试使用Expressions来编写它。

private int? GetNthOccurrance(string inputString, char charToFind, int occurranceToFind)
{
    int totalOccurrances = inputString.ToCharArray().Count(c => c == charToFind);
    if (totalOccurrances < occurranceToFind || occurranceToFind <= 0)
    {
        return null;
    }

    var charIndex =
        Enumerable.Range(0, inputString.Length - 1)
            .Select(r => new { Position = r, Char = inputString[r], Count = 1 })
            .Where(r => r.Char == charToFind);


    return charIndex
        .Select(c => new
        {
            c.Position,
            c.Char,
            Count = charIndex.Count(c2 => c2.Position <= c.Position)
        })
        .Where(r => r.Count == occurranceToFind)
        .Select(r => r.Position)
        .First();
}

并进行测试以证明这一点:

Assert.AreEqual(0, GetNthOccurrance(input, 'h', 1)); 
Assert.AreEqual(3, GetNthOccurrance(input, 'l', 2));
Assert.IsNull(GetNthOccurrance(input, 'z', 1));
Assert.IsNull(GetNthOccurrance(input, 'h', 10));

答案 4 :(得分:0)

您可以调用.IndexOf(char,position)从所需位置进行搜索,因此您应该调用它3次(但是,在每次调用之后,您还应该检查是否找到了某些内容)。

答案 5 :(得分:0)

int pos = -1;
for ( int k = 0; k < 3; ++k )
{
  pos = s.indexOf( ':', pos+1 );
  // Check if pos < 0...
}

答案 6 :(得分:0)

有点丑陋,但另一种方法(已发布的其他方法)有效:

public int FindThirdColonIndex(string msg)
{       
    for (int i = 0, colonCount = 0; i < msg.Length; i++)
    {
        if (msg[i] == ':' && ++colonCount == 3) { return i; }
    }

    // Not found
    return -1;
}

答案 7 :(得分:0)

这是一个递归实现(对于字符串而不是char) - 作为扩展方法,模仿框架方法的格式。

您需要做的就是在扩展方法中将'字符串值'更改为'char value'并相应地更新测试并且它将起作用...我很乐意这样做并且如果有人有兴趣发布它吗?

public static int IndexOfNth(
    this string input, string value, int startIndex, int nth)
{
    if (nth < 1)
        throw new NotSupportedException("Param 'nth' must be greater than 0!");
    if (nth == 1)
        input.IndexOf(value, startIndex);
    return
        input.IndexOfNth(value, input.IndexOf(value, startIndex) + 1, --nth);
}

此外,这里有一些(MBUnit)单元测试可以帮助你(证明它是正确的):

[Test]
public void TestIndexOfNthWorksForNth1()
{
    const string input = "foo<br />bar<br />baz<br />";
    Assert.AreEqual(3, input.IndexOfNth("<br />", 0, 1));
}

[Test]
public void TestIndexOfNthWorksForNth2()
{
    const string input = "foo<br />whatthedeuce<br />kthxbai<br />";
    Assert.AreEqual(21, input.IndexOfNth("<br />", 0, 2));
}

[Test]
public void TestIndexOfNthWorksForNth3()
{
    const string input = "foo<br />whatthedeuce<br />kthxbai<br />";
    Assert.AreEqual(34, input.IndexOfNth("<br />", 0, 3));
}

答案 8 :(得分:0)

请在类似问题上查看此答案: https://stackoverflow.com/a/46460083/7673306
它提供了一种方法,用于查找指定字符串中特定字符第n次出现的索引。

在您的具体情况下,它将如下实施:

int index = IndexOfNthCharacter("error: file.ext: line 10: invalid command [test:)]", 3, ':');

答案 9 :(得分:0)

简单地用char分割字符串。 这为您提供了一个数组,您可以将其用于定位所需的内容。

var stringToSplit = "one_two_three_four";
var splitString = stringToSplit.Split("_");          
if (splitString.length > 3){
    var newString = $"{splitResult[0]}_{splitResult[1]}_{splitResult[2]}";
}