Kry die indeks van die nde voorkoms van 'n string?
Vra
As ek ontbreek 'n duidelike ingeboude metode, wat is die vinnigste manier om te kry die n ste voorkoms van 'n string binne 'n string?
Ek besef dat ek kon loop die IndexOf 'n> metode deur die opdatering van sy begin indeks op elke iterasie van die lus. Maar doen dit op hierdie manier lyk verkwistende vir my.
Oplossing
Dit is basies wat jy hoef te doen - of ten minste, dis die maklikste oplossing. Al wat jy wil word "mors" is die koste van N metode aanroepingen - jy sal nie eintlik elk geval twee keer nagaan, as jy daaroor dink. (IndexOf sal so gou as dit die wedstryd vind om terug te keer, en jy sal aanhou gaan uit waar dit opgehou het.)
Ander wenke
Jy moet regtig kan die gewone uitdrukking /((s).*?){n}/
gebruik om te soek na n-de voorkoms van substring s
.
In C # is dit dalk so lyk:
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;
}
}
Nota:. Ek het Regex.Escape
bygevoeg oorspronklike oplossing te laat soek karakters wat spesiale betekenis aan regex enjin het
Dit is basies wat jy hoef te doen - of ten minste, dis die maklikste oplossing. Al wat jy wil word "mors" is die koste van N metode aanroepingen - jy sal nie eintlik elk geval twee keer nagaan, as jy daaroor dink. (IndexOf sal so gou as dit die wedstryd vind om terug te keer, en jy sal aanhou gaan uit waar dit opgehou het.)
Hier is die rekursiewe implementering (van die bo idee ) as 'n uitbreiding metode, bootsen die formaat van die raamwerk metode (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);
}
Ook hier is 'n paar (MBUnit) eenheid toetse wat jou kan help (om dit te bewys is korrek):
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;
}
of in C # met uitbreiding metodes
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;
}
Miskien sal dit ook lekker om te werk met die String.Split()
Metode en kyk of die versoek voorkoms is in die skikking, as jy nie die indeks moet wees, maar die waarde van die indeks
Na 'n paar benchmarking, dit lyk na die eenvoudigste en mees doeltreffende oplossing wees
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;
skryf van 'n funksie van wat huiswerk
Dit kan dit doen:
Console.WriteLine(str.IndexOf((@"\")+2)+1);