명백한 내장 방법이없는 경우가 아니면 문자열 내 에서 n 번째 문자열 을 얻는 가장 빠른 방법은 무엇 입니까?
루프가 반복 될 때마다 시작 인덱스를 업데이트 하여 IndexOf 메서드를 반복 할 수 있다는 것을 알고 있습니다. 그러나 이렇게하는 것은 나에게 낭비적인 것 같습니다.
명백한 내장 방법이없는 경우가 아니면 문자열 내 에서 n 번째 문자열 을 얻는 가장 빠른 방법은 무엇 입니까?
루프가 반복 될 때마다 시작 인덱스를 업데이트 하여 IndexOf 메서드를 반복 할 수 있다는 것을 알고 있습니다. 그러나 이렇게하는 것은 나에게 낭비적인 것 같습니다.
답변:
이것이 기본적으로해야 할 일입니다. 또는 적어도 가장 쉬운 솔루션입니다. "낭비"하는 것은 n 개의 메서드 호출 비용입니다. 생각해 보면 실제로 두 번 확인하지 않을 것입니다. (IndexOf는 일치 항목을 찾는 즉시 반환되며 중단 된 위치부터 계속 진행됩니다.)
StringUtils.ordinalIndexOf()
. 모든 Linq 및 기타 멋진 기능이 포함 된 C #에는 이에 대한 기본 지원 기능이 없습니다. 그리고 예, 파서 및 토크 나이저를 다루는 경우 지원을받는 것이 매우 중요합니다.
string
:
실제로 정규식 /((s).*?){n}/
을 사용하여 substring의 n 번째 발생을 검색 할 수 있습니다 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
정규식 엔진에 특별한 의미가있는 문자를 검색 할 수 있도록 원래 솔루션에 추가 했습니다.
value
합니까? 내 경우에는 내가 점을 찾고 있었다 msdn.microsoft.com/en-us/library/...
이것이 기본적으로해야 할 일입니다. 또는 적어도 가장 쉬운 솔루션입니다. "낭비"하는 것은 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;
}
index
. 처음에는 -1 로 설정하여 수정할 수 있습니다 .
"BOB".IndexOf("B")
0을 반환하면이 함수를 사용해야합니다IndexOfOccurence("BOB", "B", 1)
IndexOfOccurence
경우 확인하지 않습니다 s
이다 null
. 그리고 경우 String.indexOf (문자열, INT32)이 발생합니다 ArgumentNullException
경우 match
입니다 null
.
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;
}
Tod의 대답은 다소 단순화 될 수 있습니다.
using System;
static class MainClass {
private static int IndexOfNth(this string target, string substring,
int seqNr, int startIdx = 0)
{
if (seqNr < 1)
{
throw new IndexOutOfRangeException("Parameter 'nth' must be greater than 0.");
}
var idx = target.IndexOf(substring, startIdx);
if (idx < 0 || seqNr == 1) { return idx; }
return target.IndexOfNth(substring, --seqNr, ++idx); // skip
}
static void Main () {
Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 1));
Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 2));
Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 3));
Console.WriteLine ("abcbcbcd".IndexOfNth("bc", 4));
}
}
산출
1
3
5
-1
이것은 그것을 할 수 있습니다 :
Console.WriteLine(str.IndexOf((@"\")+2)+1);