92 votes

Trouver la Nième occurrence d'un caractère dans une chaîne de caractères

J'ai besoin d'aide pour créer une méthode C# qui renvoie l'indice de la Nième occurrence d'un caractère dans une chaîne de caractères.

Par exemple, la 3ème occurrence du caractère 't' dans la chaîne "dtststxtu" est de 5.
(Notez que la chaîne a 4 t s.)

0 votes

Avec quoi avez-vous travaillé jusqu'à présent ?

3 votes

J'ai modifié votre réponse pour exprimer plus clairement ce que vous voulez. J'espère que vous obtiendrez des réponses qui correspondent à votre question. Le fait de ne pas parler couramment l'anglais n'est pas un problème sur Stack Overflow, vous pouvez toujours ajouter une ligne demandant à quelqu'un de plus compétent de modifier votre question et de la nettoyer, mais vous devez vous-même vous efforcer de fournir des exemples dans la question afin que les gens comprennent ce dont vous avez besoin.

106voto

Mike Two Points 16706
public int GetNthIndex(string s, char t, int n)
{
    int count = 0;
    for (int i = 0; i < s.Length; i++)
    {
        if (s[i] == t)
        {
            count++;
            if (count == n)
            {
                return i;
            }
        }
    }
    return -1;
}

Cela pourrait être rendu beaucoup plus propre, et il n'y a pas de contrôle sur l'entrée.

7 votes

Excellente approche. Agréable et propre, facile à lire, facile à entretenir, et excellente performance.

1 votes

J'adore les boucles comme celles-ci, non seulement elles donnent d'excellentes performances, mais vous ne pouvez pas vous tromper avec elles puisque tout est clair comme de l'eau de roche et juste devant vos yeux. Vous écrivez un linq et un développeur le met dans une boucle sans comprendre le coût et tout le monde se demande où est le goulot d'étranglement des performances.

22voto

shalin shah Points 91

Il y a un bug mineur dans la solution précédente.

Voici un code mis à jour :

s.TakeWhile(c => (n -= (c == t ? 1 : 0)) > 0).Count();

1 votes

Que retourne-t-il si le caractère n'est pas trouvé ?

0 votes

Elle renvoie la longueur/comptage de la chaîne s. Vous devez vérifier cette valeur.

9voto

Tod Thomson Points 1145

Voici une mise en œuvre récursive - en tant que méthode d'extension, imitant le format de la ou des méthodes du cadre :

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

    return input.IndexOfNth(value, input.IndexOf(value, startIndex) + 1, --nth);
}

Voici également quelques tests unitaires (MBUnit) qui pourraient vous aider (à prouver que c'est correct) :

[Test]
public void TestIndexOfNthWorksForNth1()
{
    const string input = "foo<br />bar<br />baz<br />";
    Assert.AreEqual(3, input.IndexOfNth("<br />", 0, 1));
}

[Test]
public void TestIndexOfNthWorksForNth2()
{
    const string input = "foo<br />whatthedeuce<br />kthxbai<br />";
    Assert.AreEqual(21, input.IndexOfNth("<br />", 0, 2));
}

[Test]
public void TestIndexOfNthWorksForNth3()
{
    const string input = "foo<br />whatthedeuce<br />kthxbai<br />";
    Assert.AreEqual(34, input.IndexOfNth("<br />", 0, 3));
}

8voto

Joel Coehoorn Points 190579

Mise à jour : Index de la Nième occurrence de la phrase unique :

int NthOccurence(string s, char t, int n)
{
    s.TakeWhile(c => n - (c == t)?1:0 > 0).Count();
}

Utilisez-les à vos risques et périls. Cela ressemble à un devoir, alors j'ai laissé quelques bogues pour que vous les trouviez :

int CountChars(string s, char t)
{
   int count = 0;
   foreach (char c in s)
      if (s.Equals(t)) count ++;
   return count;
}

.

int CountChars(string s, char t)
{
     return s.Length - s.Replace(t.ToString(), "").Length;
}

.

int CountChars(string s, char t)
{
    Regex r = new Regex("[\\" + t + "]");
    return r.Match(s).Count;
}

4 votes

Votre exemple en une ligne ne fonctionne pas car la valeur de n n'est jamais modifiée.

2 votes

Belle solution, bien que ce ne soit pas un vrai "one-liner" car une variable doit être définie hors de la portée du lambda. s.TakeWhile(c => ((n -= (c == 't')) ? 1 : 0) > 0).Count() ;

14 votes

1, "alors j'ai laissé quelques bugs là-dedans pour que vous les trouviez".

3voto

Andrew Hare Points 159332

La réponse de Joel est bonne (et j'ai voté pour elle). Voici une solution basée sur LINQ :

yourString.Where(c => c == 't').Count();

2 votes

@Andrew - vous pouvez raccourcir cette procédure en sautant le Where et en passant le prédicat à la Count méthode. Non pas qu'il y ait quelque chose de mal à cette méthode.

11 votes

Cela ne va-t-il pas simplement trouver le nombre d'occurrences d'un caractère plutôt que l'indice de la nième ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X