That's basically what you need to do - or at least, it's the easiest solution. All you'd be "wasting" is the cost of n method invocations - you won't actually be checking any case twice, if you think about it. (IndexOf will return as soon as it finds the match, and you'll keep going from where it left off.)
Oto rekurencyjna realizacja (wyzej idei) jako metodę rozszerzenia, dokładnie taki efekt formatu metody ramowej (ów):
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)
return input.IndexOf(value, startIndex);
var idx = input.IndexOf(value, startIndex);
if (idx == -1)
return -1;
return input.IndexOfNth(value, idx + 1, --nth);
}
Także tutaj są niektóre (MBUnit) testy jednostkowe które t pomóc (to udowodnić jest poprawna):
using System;
using MbUnit.Framework;
namespace IndexOfNthTest
{
[TestFixture]
public class Tests
{
//has 4 instances of the
private const string Input = "TestTest";
private const string Token = "Test";
/* Test for 0th index */
[Test]
public void TestZero()
{
Assert.Throws<NotSupportedException>(
() => Input.IndexOfNth(Token, 0, 0));
}
/* Test the two standard cases (1st and 2nd) */
[Test]
public void TestFirst()
{
Assert.AreEqual(0, Input.IndexOfNth("Test", 0, 1));
}
[Test]
public void TestSecond()
{
Assert.AreEqual(4, Input.IndexOfNth("Test", 0, 2));
}
/* Test the 'out of bounds' case */
[Test]
public void TestThird()
{
Assert.AreEqual(-1, Input.IndexOfNth("Test", 0, 3));
}
/* Test the offset case (in and out of bounds) */
[Test]
public void TestFirstWithOneOffset()
{
Assert.AreEqual(4, Input.IndexOfNth("Test", 4, 1));
}
[Test]
public void TestFirstWithTwoOffsets()
{
Assert.AreEqual(-1, Input.IndexOfNth("Test", 8, 1));
}
}
}
Podobne: http://stackoverflow.com/a/9908392/1305911 – JNF
Używałbym wyrażeń regularnych do tego, to musisz optymalnie sposób dopasowywania ciągu znaków w ciągu znaków. To w jednym z pięknych DSL-ów, z których wszyscy powinniśmy korzystać, jeśli to możliwe. [Przykład] (http://www.regular-expressions.info/dotnet.html "Link") w VB.net kod jest prawie taki sam w C#. – bovium
Chciałbym umieścić dobre pieniądze na wersji wyrażeń regularnych, które są znacznie trudniejsze do uzyskania, niż "zachować pętlę i robić proste String.IndexOf". Wyrażenia regularne mają swoje miejsce, ale nie powinny być używane, gdy istnieją prostsze alternatywy. –