Подтвердить что ты не робот

Получить индекс n-го вхождения char в строку

Я пытаюсь создать функцию, которая возвращает индекс N-го вхождения данного char в строку.

Вот моя попытка:

private int IndexOfNth(string str, char c, int n)
{
    int index = str.IndexOf(c) + 1;
    if (index >= 0)
    {
        string temp = str.Substring(index, str.Length - index);
        for (int j = 1; j < n; j++)
        {
            index = temp.IndexOf(c) + 1;
            if (index < 0)
            {
                return -1;
            }
            temp = temp.Substring(index, temp.Length - index);
        }
        index = index + (str.Length);
    }
    return index;
}

Это должно найти первое вхождение, отрубить эту переднюю часть строки, найти первое вхождение из новой подстроки и продолжать и продолжать, пока не получит индекс n-го вхождения. Однако мне не удалось понять, как индекс конечной подстроки будет смещен от исходного фактического индекса в исходной строке. Как это сделать?

Также, как побочный вопрос, если я хочу, чтобы char был символом табуляции, передаю эту функцию '\ t' или что?

4b9b3361

Ответ 1

Используя LINQ, найдите индекс 5'th a в строке aababaababa:

var str = "aababaababa";
var ch = 'a';
var n = 5;
var result = str
  .Select((c, i) => new { c, i })
  .Where(x => x.c == ch)
  .Skip(n - 1)
  .FirstOrDefault();
return result != null ? result.i : -1;

Ответ 2

Не делай этого; IndexOf принимает второй параметр, который указывает, с чего начать.

private static int IndexOfNth(string str, char c, int n) {
    int s = -1;

    for (int i = 0; i < n; i++) {
        s = str.IndexOf(c, s + 1);

        if (s == -1) break;
    }

    return s;
}

Ответ 3

Взятие всех этих подстрок кажется мне довольно расточительным. Почему бы просто не зациклиться?

private int IndexOfNth(string str, char c, int n)
{
    int remaining = n;
    for (int i = 0; i < str.Length; i++)
    {
        if (str[i] == c)
        {
            remaining--;
            if (remaining == 0)
            {
                return i;
            }
        }
    }
    return -1;
}

(я рассмотрел использование IndexOf в цикле, как решение minitech, но решил, что это было немного странно. Конечно, конечно. Оба в основном выполняют ту же работу, только когда-либо проверяя каждый символ один раз. Использование IndexOf может быть немного более эффективным, но идти в зависимости от того, что вы найдете более читаемым.)

Ответ 4

Я сначала думаю о том, как получить доступ к коллекции с помощью Linq.

  // 0-based n.
char result = str
  .Where(x => x == c)
  .Skip(n)
  .FirstOrDefault();

Затем я распакую linq и добавлю индексированную итерацию.

int foundCount = -1;
for(int position = 0; position < str.Length; position++)
{
  char x = str[position];
  if (x == c)
  {
    foundCount += 1;
    // 0-based n
    if (foundCount == n)
    {
      return position;
    }
  }
}
return -1;

Тогда я думаю о том: что, если этот метод вернет все индексы, чтобы я мог их запросить:

public IEnumerable<int> IndexesOf(string str, char c)
{
  for(int position = 0; position < str.Length; position++)
  {
    char x = str[position];
    if (x == c)
    {
      yield return position;
    }
  }
}

Вызывается:

int position = IndexesOf(str, c)
 .Skip(n) // 0-based n
 .DefaultIfEmpty(-1)
 .First();

Ответ 6

Не тестировалось, но что-то вроде этого должно работать:

private int IndexOfNth(string str, char c, int n)
{
    int index = -1;
    while (n-- > 0)
    {
        index = str.IndexOf(c, index + 1);
        if (index == -1) break;
    }
    return index;
}

Ответ 7

Не видел, чтобы кто-нибудь использовал CharEnumerator еще...

    public Int32 getNthIndex(string str, char c, Int32 n)
    {
        Int32 index = 0;
        Int32 count = 0;
        if (str != null && str.Length > 0 && !(n < 1))
        {
            CharEnumerator scanner = str.GetEnumerator();
            while (scanner.MoveNext())
            {
                if (scanner.Current == c) { count++; }
                if (count == n) { break; }
                index++;
            }
            if (count < n) { index = -1; }
        }
        if (count == 0) { return -1; } else { return index; }
    }

Должно быть довольно эффективно, подстроки или что-то еще, просто просматривайте строку, которую вы даете, и держите счет.

Ответ 8

Вы можете использовать следующий метод, который вернет n-ое вхождение указанного символа в указанной строке.

public static int IndexOfNthCharacter(string str, int n, char c) {
    int index = -1;
    if (!str.Contains(c.ToString()) || (str.Split(c).Length-1 < n)) {
        return -1;
    }
    else {
        for (int i = 0; i < str.Length; i++) {
            if (n > 0) {            
                index++;
            }
            else {
                return index;
            }
            if (str[i] == c) {
                n--;
            }
        }
        return index;
    }
}

Обратите внимание, что если искомый символ не существует в строке, которую вы ищете, или номер поиска, который вы ищете, больше, чем тот, что существует в строке, тогда этот метод вернет -1.