[c#] 문자열에서 N 번째 문자 찾기

문자열에서 N 번째 문자의 인덱스를 반환하는 C # 메서드를 만드는 데 도움이 필요합니다.

예를 들어, 't'문자열에서 세 번째로 나오는 문자 "dtststxtu"는 5입니다
(문자열에는 4 t초가 있습니다.)



답변

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

훨씬 더 깔끔하게 만들 수 있으며 입력에 대한 검사가 없습니다.


답변

이전 솔루션에는 사소한 버그가 있습니다.

다음은 업데이트 된 코드입니다.

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


답변

다른 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!");


답변

다음은 프레임 워크 메소드의 형식을 모방 한 확장 메소드로서의 재귀 구현입니다.

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


답변

업데이트 : 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;
}


답변

ranomore는 Joel Coehoorn의 한 줄짜리가 작동하지 않는다고 올바르게 언급했습니다.

여기서 두 라이너 수행 업무, 문자의 출현 n 번째의 0 기반 인덱스를 반환 문자열 확장 방법 또는 -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;
    }
}


답변

Joel의 대답은 좋습니다 (그리고 나는 그것을 찬성했습니다). 다음은 LINQ 기반 솔루션입니다.

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