Найти N-е вхождение символа в строку - PullRequest
71 голосов
/ 03 апреля 2010

Мне нужна помощь в создании метода C #, который возвращает индекс N-го вхождения символа в строку.

Например, третье вхождение символа 't' в строке "dtststxtu" равно 5.
(Обратите внимание, что строка имеет 4 t с.)

Ответы [ 21 ]

75 голосов
/ 03 апреля 2010
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;
}

Это можно сделать намного чище, и на входе нет никаких проверок.

19 голосов
/ 28 марта 2012

В предыдущем решении есть небольшая ошибка.

Вот обновленный код:

s.TakeWhile(c => (n -= (c == t ? 1 : 0)) > 0).Count();
11 голосов
/ 03 апреля 2010

Обновление: Индекс N-го числа однострочных:

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

Используйте их на свой страх и риск. Это похоже на домашнюю работу, поэтому я оставил несколько ошибок, чтобы вы могли найти:

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;
}
9 голосов
/ 03 апреля 2010

Вот еще одно решение LINQ:

string input = "dtststx";
char searchChar = 't';
int occurrencePosition = 3; // third occurrence of the char
var result = input.Select((c, i) => new { Char = c, Index = i })
                  .Where(item => item.Char == searchChar)
                  .Skip(occurrencePosition - 1)
                  .FirstOrDefault();

if (result != null)
{
    Console.WriteLine("Position {0} of '{1}' occurs at index: {2}",
                        occurrencePosition, searchChar, result.Index);
}
else
{
    Console.WriteLine("Position {0} of '{1}' not found!",
                        occurrencePosition, searchChar);
}

Просто для удовольствия, вот решение Regex. Я видел, что некоторые люди первоначально использовали Regex для подсчета, но когда вопрос изменился, никаких обновлений сделано не было. Вот как это можно сделать с помощью Regex - опять же, просто для удовольствия. Традиционный подход лучше всего подходит для простоты.

string input = "dtststx";
char searchChar = 't';
int occurrencePosition = 3; // third occurrence of the char

Match match = Regex.Matches(input, Regex.Escape(searchChar.ToString()))
                   .Cast<Match>()
                   .Skip(occurrencePosition - 1)
                   .FirstOrDefault();

if (match != null)
    Console.WriteLine("Index: " + match.Index);
else
    Console.WriteLine("Match not found!");
8 голосов
/ 22 марта 2011

Вот рекурсивная реализация - как метод расширения, имитирующий формат метода (ов) фреймворка:

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

Кроме того, вот некоторые (MBUnit) модульные тесты, которые могут вам помочь (чтобы доказать, что это правильно):

[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));
}
5 голосов
/ 23 июня 2011

Раномор правильно прокомментировал, что однострочный текст Джоэла Кехорна не работает.

Вот две строки, которые выполняет , метод расширения строки, который возвращает основанный на 0 индекс n-го вхождения символа или -1, если n-го вхождения не существует:

public static class StringExtensions
{
    public static int NthIndexOf(this string s, char c, int n)
    {
        var takeCount = s.TakeWhile(x => (n -= (x == c ? 1 : 0)) > 0).Count();
        return takeCount == s.Length ? -1 : takeCount;
    }
}
4 голосов
/ 03 апреля 2010

Хороший ответ Джоэла (и я проголосовал за него).Вот решение на основе LINQ:

yourString.Where(c => c == 't').Count();
3 голосов
/ 17 июня 2015

Я добавляю еще один ответ, который выполняется довольно быстро по сравнению с другими методами

private static int IndexOfNth(string str, char c, int nth, int startPosition = 0)
{
    int index = str.IndexOf(c, startPosition);
    if (index >= 0 && nth > 1)
    {
        return  IndexOfNth(str, c, nth - 1, index + 1);
    }

    return index;
}
3 голосов
/ 22 мая 2015
string result = "i am 'bansal.vks@gmail.com'"; // string

int in1 = result.IndexOf('\''); // get the index of first quote

int in2 = result.IndexOf('\'', in1 + 1); // get the index of second

string quoted_text = result.Substring(in1 + 1, in2 - in1); // get the string between quotes
3 голосов
/ 02 апреля 2014
public int GetNthOccurrenceOfChar(string s, char c, int occ)
{
    return String.Join(c.ToString(), s.Split(new char[] { c }, StringSplitOptions.None).Take(occ)).Length;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...