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.)
Aquí está la implementación recursiva (de lo anterior idea) como un método de extensión, imitando el formato del método del marco (s):
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);
}
Además, he aquí algunas pruebas de unidad (MBUnit) que t ayuda que (para demostrar que es correcta):
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));
}
}
}
Similar: http://stackoverflow.com/a/9908392/1305911 – JNF
Utilizaría expresiones regulares para eso, entonces tiene que optimizar forma de hacer coincidir la cadena dentro de la cadena. Esto en una de las hermosas DSL que todos deberíamos usar cuando sea posible. [Un ejemplo] (http://www.regular-expressions.info/dotnet.html "Link") en VB.net el código es casi el mismo en C#. – bovium
Me gustaría poner un buen dinero en la versión de expresiones regulares que es mucho más difícil de obtener a la derecha que "seguir haciendo bucles y haciendo simple String.IndexOf". Las expresiones regulares tienen su lugar, pero no deberían usarse cuando existen alternativas más simples. –