有没有一种命令可以获取字符串中第三个字符的索引?例如:
error: file.ext: line 10: invalid command [test:)]
在上面的句子中,我想要获取第三个冒号的索引,即紧挨着数字10旁边的那个冒号。我知道可以使用string.IndexOf和string.LastIndexOf方法,但在这种情况下,我想要获取字符第三次出现时的索引。
有没有一种命令可以获取字符串中第三个字符的索引?例如:
error: file.ext: line 10: invalid command [test:)]
在上面的句子中,我想要获取第三个冒号的索引,即紧挨着数字10旁边的那个冒号。我知道可以使用string.IndexOf和string.LastIndexOf方法,但在这种情况下,我想要获取字符第三次出现时的索引。
String.IndexOf
可以获取第一个字符的索引,但它有一些重载函数可以指定开始搜索的位置。因此,您可以使用第一个 IndexOf
的结果加一作为下一个 IndexOf
的起始点。然后只需累积足够次数的索引:
var offset = myString.IndexOf(':');
offset = myString.IndexOf(':', offset+1);
var result = myString.IndexOf(':', offset+1);
除非你知道myString
中至少包含三个冒号,否则添加错误处理。
IndexOf
后检查 offset
是否为非负数(请注意,您输入了 Index
),并且我会在每个调用后使用不同的变量分别命名为 firstOffset
、secondOffset
和 thirdOffset
。有些人可能认为这样做过分了,但他们只是抵制不良根深蒂固的习惯。 - jasonIndex
-> IndexOf
:修复。请注意检查-1结果。我认为这里使用三个单独的变量有些过度(如果我知道,即可以断言有足够的字符,我会在一个表达式中完成整个操作。但是我喜欢紧凑的代码,因为通常通过消除噪音更易读)。 - Richardint
并将 offset
更改为 xOffset
,其中 x
分别为 first
、second
或 third
。此外,调试也更加友好。 - jason你可以编写类似下面的代码:
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 (: ]"
}
这个问题已经有几种非常好的回答了 - 但我决定尝试使用表达式来写。
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));
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));
}
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;
}
int index = IndexOfNthCharacter("error: file.ext: line 10: invalid command [test:)]", 3, ':');
只需按字符拆分字符串即可。 这将给您一个数组,然后您可以使用它来定位您想要的内容。
var stringToSplit = "one_two_three_four";
var splitString = stringToSplit.Split("_");
if (splitString.length > 3){
var newString = $"{splitResult[0]}_{splitResult[1]}_{splitResult[2]}";
}