is there a command that can get the third index of a character in a string? For example:
error: file.ext: line 10: invalid command [test:)]
This has already been answered several very good ways - but I decided to try and write it using 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();
}
and Tests to prove it too:
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));
Here is a recursive implementation (for string not char) - as an extension method, mimicing the format of the framework method(s).
All you need to do is change 'string value' to 'char value' in the extension method and update the tests accordingly and it will work... I'm happy to do that and post it if anyone is interested?
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);
}
Also, here are some (MBUnit) unit tests that might help you (to prove it is correct):
[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));
}
A little ugly, but an alternative approach (to the others already posted) that works:
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;
}
You can call .IndexOf(char, position) to search from desired position, thus you should call it 3 times (but, after each call you should also check if something is found).