C#字符串中字符的第三个索引
是否有一个命令可以获取字符串中字符的第三个索引? 例如:
error: file.ext: line 10: invalid command [test:)]
在上面的句子中,我想要第3个冒号的索引,10个旁边的那个。我怎么能这样做? 我知道string.IndexOf和string.LastIndexOf,但在这种情况下我想得到第三次使用时字符的索引。
String.IndexOf
会得到第一个索引,但是有重载给出一个起点。 因此,您可以使用第一个IndexOf
加1的结果作为下一个的起点。 然后只需累积索引足够次数:
var offset = myString.IndexOf(':'); offset = myString.IndexOf(':', offset+1); var result = myString.IndexOf(':', offset+1);
除非您知道myString
包含至少三个冒号,否则添加error handling。
你可以这样写:
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);
我猜你想把那个字符串解析成不同的部分。
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 (: ]" }
这已经得到了几个很好的解决方法 – 但我决定尝试使用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(); }
和测试来certificate它:
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));
您可以调用.IndexOf(char,position)从所需位置进行搜索,因此您应该调用它3次(但是,在每次调用之后,您还应该检查是否找到了某些内容)。
int pos = -1; for ( int k = 0; k < 3; ++k ) { pos = s.indexOf( ':', pos+1 ); // Check if pos < 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; }
这是一个递归实现(对于字符串而不是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)unit testing可能会帮助你(certificate它是正确的):
[Test] public void TestIndexOfNthWorksForNth1() { const string input = "foo
bar
baz
"; Assert.AreEqual(3, input.IndexOfNth("
", 0, 1)); } [Test] public void TestIndexOfNthWorksForNth2() { const string input = "foo
whatthedeuce
kthxbai
"; Assert.AreEqual(21, input.IndexOfNth("
", 0, 2)); } [Test] public void TestIndexOfNthWorksForNth3() { const string input = "foo
whatthedeuce
kthxbai
"; Assert.AreEqual(34, input.IndexOfNth("
", 0, 3)); }
请在类似问题上查看此答案: https : //stackoverflow.com/a/46460083/7673306
它提供了一种方法,用于查找指定字符串中特定字符第n次出现的索引。
在您的具体情况下,它将实现如下:
int index = IndexOfNthCharacter("error: file.ext: line 10: invalid command [test:)]", 3, ':');