문자열에 10 자 중 하나가 포함되어 있는지 확인


107

C #을 사용하고 있으며 문자열에 *, &, # 등 10 개의 문자 중 하나가 포함되어 있는지 확인하고 싶습니다.

가장 좋은 방법은 무엇입니까?


1
문자 중 하나가 있는지 또는 해당 문자 중 "하나"(예 : 정확히 하나) 만 포함되어 있는지 확인 하시겠습니까?
Reed Copsey

답변:


210

다음은 내 관점에서 가장 간단한 방법입니다.

var match = str.IndexOfAny(new char[] { '*', '&', '#' }) != -1

또는 읽기 쉬운 형식으로 :

var match = str.IndexOfAny("*&#".ToCharArray()) != -1

필요한 컨텍스트 및 성능에 따라 char 배열을 캐시 할 수도 있고 원하지 않을 수도 있습니다.


char 배열을 인스턴스화 할 때 유형이 생략 될 수 있으며 유추됩니다.
Palec

40

다른 사람들이 말했듯이 IndexOfAny를 사용하십시오. 그러나 다음과 같이 사용합니다.

private static readonly char[] Punctuation = "*&#...".ToCharArray();

public static bool ContainsPunctuation(string text)
{
    return text.IndexOfAny(Punctuation) >= 0;
}

이렇게하면 호출 할 때마다 새 어레이를 만들지 않아도됩니다. 문자열은 일련의 문자 리터럴 인 IMO보다 스캔하기가 더 쉽습니다.

물론 이것을 한 번만 사용할 것이므로 낭비되는 생성이 문제가되지 않는다면 다음 중 하나를 사용할 수 있습니다.

private const string Punctuation = "*&#...";

public static bool ContainsPunctuation(string text)
{
    return text.IndexOfAny(Punctuation.ToCharArray()) >= 0;
}

또는

public static bool ContainsPunctuation(string text)
{
    return text.IndexOfAny("*&#...".ToCharArray()) >= 0;
}

어떤 것이 더 읽기 쉬운 지, 다른 곳에서 구두점 문자를 사용할지 여부 및 메서드가 호출되는 빈도에 따라 다릅니다.


편집 : 문자열에 정확히 하나 의 문자 가 포함되어 있는지 확인하는 Reed Copsey의 방법에 대한 대안이 있습니다 .

private static readonly HashSet<char> Punctuation = new HashSet<char>("*&#...");

public static bool ContainsOnePunctuationMark(string text)
{
    bool seenOne = false;

    foreach (char c in text)
    {
        // TODO: Experiment to see whether HashSet is really faster than
        // Array.Contains. If all the punctuation is ASCII, there are other
        // alternatives...
        if (Punctuation.Contains(c))
        {
            if (seenOne)
            {
                return false; // This is the second punctuation character
            }
            seenOne = true;
        }
    }
    return seenOne;
}

성능이 문제인 경우 char 배열을 캐싱 할 가치가 있다고 생각하지만 컨텍스트에 따라 가치가 없을 수도 있습니다.
Noldorin

1
예, 한 번 실행될 메서드에서만 사용한다면 가치가 없을 수 있습니다. 하지만 성능뿐만 아니라 가독성도 향상되었다고 생각합니다. ToCharArray물론 필요한 경우 "인라인"형식을 사용할 수 있습니다 .
Jon Skeet

1
@canon : 세트는 얼마나 큽니까? 아주 작은 세트의 경우 Array.Contains가 더 빠를 것으로 예상합니다. 큰 세트의 경우 HashSet은 마일로 이길 가능성이 있습니다.
Jon Skeet

5

문자가 포함되어 있는지 확인하려면 다른 곳에서 제안한대로 string.IndexOfAny를 사용하는 것이 좋습니다.

문자열 에 10 개의 문자 중 정확히 하나만 포함되어 있는지 확인 하려면 조금 더 복잡해집니다. 가장 빠른 방법은 교차로를 확인한 다음 중복을 확인하는 것입니다.

private static char[] characters = new char [] { '*','&',... };

public static bool ContainsOneCharacter(string text)
{
    var intersection = text.Intersect(characters).ToList();
    if( intersection.Count != 1)
        return false; // Make sure there is only one character in the text

    // Get a count of all of the one found character
    if (1 == text.Count(t => t == intersection[0]) )
        return true;

    return false;
}

예-이 경우 단일 루프가 아마도 더 빠르다고 생각합니다. 특히 작은 구두점 세트가 있습니다. 어떤 것이 정말 더 빠른지 확인하기 위해 큰 문자열로 이것을 테스트 해보고 싶습니다.
Reed Copsey

1
어차피 두 줄의 교차점을 찾는 것은 한 글자 씩 이동해야 할 것 같아서 어떻게 더 빠를 지 모르겠습니다 ... 제 제안 된 경로는 단일 패스를 사용할뿐만 아니라 "조기 아웃"옵션. 텍스트 만 자하는 경우 상상,하지만 첫 번째 두 사람은 모두 "*":)입니다
존 소총


1
var specialChars = new[] {'\\', '/', ':', '*', '<', '>', '|', '#', '{', '}', '%', '~', '&'};

foreach (var specialChar in specialChars.Where(str.Contains))
{
    Console.Write(string.Format("string must not contain {0}", specialChar));
}

0

여러분 모두 감사합니다! (그리고 주로 Jon!) :이를 통해 다음과 같이 작성할 수있었습니다.

    private static readonly char[] Punctuation = "$€£".ToCharArray();

    public static bool IsPrice(this string text)
    {
        return text.IndexOfAny(Punctuation) >= 0;
    }

특정 문자열이 실제로 가격인지 또는 '표시하기에 너무 낮음'과 같은 문장인지 감지하는 좋은 방법을 찾고있었습니다.


2
나는 이것이 오래되었다는 것을 알고 있지만 이것은 통화를 일치시키는 특히 좋은 방법이 아닙니다. 누군가 "Ke $ ha"라고 쓰면 가격으로 일치 할 것입니다 ... 대신 적절한 방법 중 하나를 참조하십시오. 여기에 정의 된 통화 감지 : stackoverflow.com/questions/7214513/…
mcse3010
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.