Frage

Wenn ich eine offensichtliche integrierte Methode bin fehlt, was ist der schnellste Weg, um die n th Vorkommen eines Strings in einem String zu bekommen?

Ich weiß, dass ich konnte Schleife des IndexOf Verfahren durch seinen Startindex der Schleife bei jeder Iteration aktualisiert wird. Aber es auf diese Weise tun, mir scheint verschwenderisch.

War es hilfreich?

Lösung

Das ist im Grunde, was Sie tun müssen - oder zumindest, es ist die einfachste Lösung. Alles, was Sie „verschwenden“ würden werden die Kosten für n Methodenaufrufe - Sie werden nicht tatsächlich zweimal jeden Fall überprüft, wenn man darüber nachdenkt. (IndexOf zurückkehren wird, sobald es die Übereinstimmung findet, und Sie halten geht, wo er unterbrochen wurde.)

Andere Tipps

Sie könnten wirklich den regulären Ausdruck /((s).*?){n}/ verwenden für n-ten Auftreten des Teil s zu suchen.

In C #, es könnte wie folgt aussehen:

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;
    }
}

. Hinweis: Ich habe Regex.Escape zur ursprünglichen Lösung gegeben Zeichen zu ermöglichen suchen, die eine besondere Bedeutung für Regex-Engine haben

  

Das ist im Grunde, was Sie tun müssen - oder zumindest, es ist die einfachste Lösung. Alles, was Sie „verschwenden“ würden werden die Kosten für n Methodenaufrufe - Sie werden nicht tatsächlich zweimal jeden Fall überprüft, wenn man darüber nachdenkt. (IndexOf zurückkehren wird, sobald es die Übereinstimmung findet, und Sie halten geht, wo er unterbrochen wurde.)

Hier ist die rekursive Implementierung (der oben Idee ) als Erweiterung Methode, um das Format der Rahmen Methode nachahmt (e):

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);
}

Auch hier sind einige (MBUnit) Unit-Tests, die Ihnen helfen (um zu beweisen, es ist richtig):

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;
}

oder in C # mit Erweiterungsmethoden

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;
}

Vielleicht wäre es auch schön, mit der String.Split() Methode zu arbeiten und überprüfen, ob die angeforderte Auftreten in dem Array ist, wenn Sie den Index nicht brauchen, aber der Wert auf dem Index

Nach einigem Benchmarking, scheint dies die einfachste und effizienteste Lösung zu sein

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;

eine Funktion aus, dass das Schreiben ist Hausaufgaben

Dies könnte es tun:

Console.WriteLine(str.IndexOf((@"\")+2)+1);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top