문자열의 N 번째 발생 색인을 얻으십니까?
문제
명백한 내장 방법이 놓치지 않는 한 N문자열 내 문자열이 발생합니까?
나는 내가 반복 할 수 있다는 것을 알고있다 인덱스 방법 루프의 각 반복에 대한 시작 색인을 업데이트하여 메소드. 그러나 이런 식으로하는 것은 나에게 낭비적인 것 같습니다.
해결책
그것은 기본적으로 당신이해야 할 일입니다. 적어도 가장 쉬운 솔루션입니다. "낭비"하는 것은 N 메소드 호출 비용입니다. 실제로 생각하면 실제로 두 번 확인하지 않습니다. (Indexof는 경기가 시작 되 자마자 돌아 오며, 그 중에서도 계속 가면 계속됩니다.)
다른 팁
당신은 실제로 정규 표현을 사용할 수 있습니다 /((s).*?){n}/
기판의 N-th 발생을 검색합니다 s
.
C#에서는 다음과 같이 보일 수 있습니다.
public static class StringExtender
{
public static int NthIndexOf(this string target, string value, int n)
{
Match m = Regex.Match(target, "((" + Regex.Escape(value) + ").*?){" + n + "}");
if (m.Success)
return m.Groups[2].Captures[n - 1].Index;
else
return -1;
}
}
메모: 나는 추가했다 Regex.Escape
리그 엔진에 특별한 의미가있는 캐릭터를 검색 할 수 있도록 독창적 인 솔루션으로.
그것은 기본적으로 당신이해야 할 일입니다. 적어도 가장 쉬운 솔루션입니다. "낭비"하는 것은 N 메소드 호출 비용입니다. 실제로 생각하면 실제로 두 번 확인하지 않습니다. (Indexof는 경기가 시작 되 자마자 돌아 오며, 그 중에서도 계속 가면 계속됩니다.)
재귀 구현은 다음과 같습니다 (위의 것 아이디어) 확장 방법으로 프레임 워크 방법의 형식을 모방합니다.
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);
}
또한 다음은 다음과 같습니다 (MBUNIT) 단위 테스트는 (정확하다는 것을 증명하기 위해) :
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));
}
}
}
private int IndexOfOccurence(string s, string match, int occurence)
{
int i = 1;
int index = 0;
while (i <= occurence && (index = s.IndexOf(match, index + 1)) != -1)
{
if (i == occurence)
return index;
i++;
}
return -1;
}
또는 확장 방법이있는 C#에서
public static int IndexOfOccurence(this string s, string match, int occurence)
{
int i = 1;
int index = 0;
while (i <= occurence && (index = s.IndexOf(match, index + 1)) != -1)
{
if (i == occurence)
return index;
i++;
}
return -1;
}
어쩌면 String.Split()
인덱스가 필요하지 않은 경우 요청 된 발생이 배열에 있는지 확인하고 인덱스의 값을 확인하십시오.
일부 벤치마킹 후 이것은 가장 단순하고 가장 효과적인 솔루션 인 것 같습니다.
public static int IndexOfNthSB(string input,
char value, int startIndex, int nth)
{
if (nth < 1)
throw new NotSupportedException("Param 'nth' must be greater than 0!");
var nResult = 0;
for (int i = startIndex; i < input.Length; i++)
{
if (input[i] == value)
nResult++;
if (nResult == nth)
return i;
}
return -1;
}
System.valuetuple ftw :
var index = line.Select((x, i) => (x, i)).Where(x => x.Item1 == '"').ElementAt(5).Item2;
그 기능을 작성하는 것은 숙제입니다
이것은 할 수 있습니다 :
Console.WriteLine(str.IndexOf((@"\")+2)+1);