Về cơ bản, đó là những gì bạn cần làm - hoặc ít nhất, đó là giải pháp dễ dàng nhất. Tất cả những gì bạn đang "lãng phí" là chi phí của n lần gọi phương thức - bạn sẽ không thực sự kiểm tra bất kỳ trường hợp nào hai lần, nếu bạn nghĩ về nó. (IndexOf sẽ quay lại ngay sau khi tìm thấy kết quả phù hợp và bạn sẽ tiếp tục từ nơi nó đã dừng lại.)
Đây là triển khai đệ quy ( ý tưởng ở trên ) như một phương thức mở rộng, bắt chước định dạng của (các) phương thức khung:
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);
}
Ngoài ra, đây là một số bài kiểm tra đơn vị (MBUnit) có thể giúp bạn (để chứng minh nó là đúng):
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));
}
}
}