Question

À moins que je manque une méthode intégrée évidente, quel est le moyen le plus rapide d’obtenir la n ème occurrence d’une chaîne dans une chaîne?

Je réalise que je pourrais boucler la IndexOf en mettant à jour son index de départ à chaque itération de la boucle. Mais le faire de cette façon me semble inutile.

Était-ce utile?

La solution

C'est essentiellement ce que vous devez faire - ou du moins, c'est la solution la plus simple. Tout ce que vous auriez "gaspillé" est le coût de n invocations de méthode - si vous y réfléchissez, vous ne vérifierez jamais deux fois aucun cas. (IndexOf reviendra dès qu'il trouvera la correspondance et vous continuerez d'avancer là où il s'était arrêté.)

Autres conseils

Vous pouvez vraiment utiliser l'expression régulière / ((s). *?) {n} / pour rechercher la nième occurrence de la sous-chaîne s .

En C #, cela pourrait ressembler à ceci:

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

Remarque: j'ai ajouté Regex.Escape à la solution d'origine pour permettre la recherche de caractères ayant une signification particulière pour le moteur d'expression régulière.

  

C'est essentiellement ce que vous devez faire - ou du moins, c'est la solution la plus simple. Tout ce que vous auriez "gaspillé" est le coût de n invocations de méthode - si vous y réfléchissez, vous ne vérifierez jamais deux fois aucun cas. (IndexOf reviendra dès qu'il trouvera la correspondance et vous continuerez d'avancer là où il s'était arrêté.)

Voici l'implémentation récursive (de l'idée ci-dessus ) en tant que méthode d'extension, reproduisant le format de la ou des méthodes-cadres:

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

De plus, voici quelques tests unitaires (MBUnit) qui pourraient vous aider (pour prouver que cela est correct):

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

ou en C # avec les méthodes d'extension

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

Peut-être serait-il également intéressant de travailler avec la méthode String.Split () et de vérifier si l'occurrence demandée est dans le tableau, si vous n'avez pas besoin de l'index, mais de la valeur l'index

Après quelques analyses comparatives, cela semble être la solution la plus simple et la plus efficace

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)). Où (x = > x.Item1 == '"'). ElementAt (5). Item2;

écrire une fonction à partir de devoirs

Cela pourrait le faire:

Console.WriteLine(str.IndexOf((@"\")+2)+1);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top