문자열에 일부 문자열이 포함되어 있는지 확인하는 방법


97

C #에서 String s에 "a", "b"또는 "c"가 포함되어 있는지 확인하고 싶습니다. 사용하는 것보다 더 좋은 솔루션을 찾고 있습니다.

if (s.contains("a")||s.contains("b")||s.contains("c"))

1
복잡한 경우에는 trie데이터 구조를 찾아보십시오 .
비참한 변수

답변:



94

음, 항상 이것이 있습니다.

public static bool ContainsAny(this string haystack, params string[] needles)
{
    foreach (string needle in needles)
    {
        if (haystack.Contains(needle))
            return true;
    }

    return false;
}

용법:

bool anyLuck = s.ContainsAny("a", "b", "c");

||그러나 비교 체인의 성능과 일치하는 것은 없습니다 .


12
이 멋진 솔루션에 새로운 짧은 구문 추가 public static bool ContainsAny(this string haystack, params string[] needles) { return needles.Any(haystack.Contains); }
simonkaspers1

간단하고 분명한 해결책. 그러나 건초 더미 문자열을 통해 여러 번 반복 할 필요가없는 사용 가능한 구현이 있습니까? 건초 더미 문자열 문자를 반복하고 바늘의 첫 번째 문자를 한 번에 순차적으로 비교하여 직접 구현할 수 있지만 이러한 사소한 솔루션이 잘 알려진 NuGet 라이브러리에서 아직 구현되지 않았다는 사실을 믿을 수 없습니다.
RollerKostr

@RollerKostr 그것은 C # (아직)에 내장되어 있지 않습니다. 그래서 왜 그런 간단한 솔루션을 위해 프로젝트에 추가 종속성을 추가합니까?
jmdon

70

다음은 거의 동일하지만 더 확장 가능한 LINQ 솔루션입니다.

new[] { "a", "b", "c" }.Any(c => s.Contains(c))

3
즉 :) ... 그렇지 않은 성능의 의미에서, 문자를 쉽게 추가 할 수 있다는 점에서 확장 성
Guffa

2
아, 물론입니다. 아마도 "더 확장 가능한"단어가 더 나은 선택이었을 것입니다.
Jeff Mercado

성능은 끔찍하지 않을 것입니다. 어쨌든 해석 된 정규 표현식보다 낫습니다.
Steven Sudit

완전성을위한 멋진 대답은 먼저 들어오는 문자열을 배열로 분할 할 수 있습니다. 예 : var splitStringArray = someString.Split ( ''); 그런 다음 다음과 같은 작업을 수행 할 수 있습니다. if (someStringArray.Any (s => otherString.Contains (s))) {// 무언가를합니다} 누군가가 명확하게 도움을주기를 바랍니다.
Tahir Khalid 2016 년

45
var values = new [] {"abc", "def", "ghj"};
var str = "abcedasdkljre";
values.Any(str.Contains);

21

정규식으로 시도 할 수 있습니다.

string s;
Regex r = new Regex ("a|b|c");
bool containsAny = r.IsMatch (s);

1
+1, 단일 문자를 찾고 있기 때문에 linq 솔루션 또는 indexOfAny가 더 효율적일 수 있습니다.
Joel Coehoorn

정규 표현식의 경우 +1. 그 IndexOfAny가 아니었다면 내가 위해 갈 것입니다 무엇
스타 브로스

1
정규 표현식은 이것에 과잉입니다.
Steven Sudit

3
사람들이 정규식이 과잉이라고 말하는 이유는 무엇입니까? 정규식이 한 번 컴파일되고 여러 번 사용되는 경우 c 만 포함되어 있거나 시작 부분에 c 만 있고 끝 부분에 a, b가있는 문자열이 있으면 정규식이 훨씬 더 효율적입니다.
bruceboughton

-, ' "와 같은 특수 문자에는 작동하지 않습니다
.`

14

특정 StringComparison(예 : 대소 문자 무시) 이 포함 된 ContainsAny가 필요한 경우이 문자열 확장 메서드를 사용할 수 있습니다.

public static class StringExtensions
{
    public static bool ContainsAny(this string input, IEnumerable<string> containsKeywords, StringComparison comparisonType)
    {
        return containsKeywords.Any(keyword => input.IndexOf(keyword, comparisonType) >= 0);
    }
}

사용 StringComparison.CurrentCultureIgnoreCase:

var input = "My STRING contains Many Substrings";
var substrings = new[] {"string", "many substrings", "not containing this string" };
input.ContainsAny(substrings, StringComparison.CurrentCultureIgnoreCase);
// The statement above returns true.

xyz”.ContainsAny(substrings, StringComparison.CurrentCultureIgnoreCase);
// This statement returns false.

2
이 답변을 개선하기위한 참고 사항입니다. params 키워드를 사용하여 더 우아하게 작성할 수 있습니다. ContainsAny (this string input, StringComparison comparisonType, params string [] containsKeywords) and use like input.ContainsAny (substrings, StringComparison.CurrentCultureIgnoreCase, "string", "many substrings"... etc)
Roma Borodov

7

이것은 "더 좋은 해결책"이고 아주 간단합니다

if(new string[] { "A", "B", ... }.Any(s=>myString.Contains(s)))

4

문자열은 문자 모음이므로 LINQ 확장 메서드를 사용할 수 있습니다.

if (s.Any(c => c == 'a' || c == 'b' || c == 'c')) ...

이것은 문자열을 한 번 스캔하고 일치가 발견 될 때까지 각 문자에 대해 문자열을 한 번 스캔하는 대신 첫 번째 발생에서 중지합니다.

예를 들어 문자 범위를 확인하는 등 원하는 표현식에 사용할 수도 있습니다.

if (s.Any(c => c >= 'a' && c <= 'c')) ...

동의합니다. 이것은 첫 번째 조건이 일치하지 않을 때 여러 스캔 문제를 해결합니다. 람다의 오버 헤드가 무엇인지 궁금하십니까? 그래도 한 번은 안됩니다.
bruceboughton

3
public static bool ContainsAny(this string haystack, IEnumerable<string> needles)
{
    return needles.Any(haystack.Contains);
}

3
List<string> includedWords = new List<string>() { "a", "b", "c" };
bool string_contains_words = includedWords.Exists(o => s.Contains(o));

2
// Nice method's name, @Dan Tao

public static bool ContainsAny(this string value, params string[] params)
{
    return params.Any(p => value.Compare(p) > 0);
    // or
    return params.Any(p => value.Contains(p));
}

Any모두를 All위해


2
    static void Main(string[] args)
    {
        string illegalCharacters = "!@#$%^&*()\\/{}|<>,.~`?"; //We'll call these the bad guys
        string goodUserName = "John Wesson";                   //This is a good guy. We know it. We can see it!
                                                               //But what if we want the program to make sure?
        string badUserName = "*_Wesson*_John!?";                //We can see this has one of the bad guys. Underscores not restricted.

        Console.WriteLine("goodUserName " + goodUserName +
            (!HasWantedCharacters(goodUserName, illegalCharacters) ?
            " contains no illegal characters and is valid" :      //This line is the expected result
            " contains one or more illegal characters and is invalid"));
        string captured = "";
        Console.WriteLine("badUserName " + badUserName +
            (!HasWantedCharacters(badUserName, illegalCharacters, out captured) ?
            " contains no illegal characters and is valid" :
            //We can expect this line to print and show us the bad ones
            " is invalid and contains the following illegal characters: " + captured));  

    }

    //Takes a string to check for the presence of one or more of the wanted characters within a string
    //As soon as one of the wanted characters is encountered, return true
    //This is useful if a character is required, but NOT if a specific frequency is needed
    //ie. you wouldn't use this to validate an email address
    //but could use it to make sure a username is only alphanumeric
    static bool HasWantedCharacters(string source, string wantedCharacters)
    {
        foreach(char s in source) //One by one, loop through the characters in source
        {
            foreach(char c in wantedCharacters) //One by one, loop through the wanted characters
            {
                if (c == s)  //Is the current illegalChar here in the string?
                    return true;
            }
        }
        return false;
    }

    //Overloaded version of HasWantedCharacters
    //Checks to see if any one of the wantedCharacters is contained within the source string
    //string source ~ String to test
    //string wantedCharacters ~ string of characters to check for
    static bool HasWantedCharacters(string source, string wantedCharacters, out string capturedCharacters)
    {
        capturedCharacters = ""; //Haven't found any wanted characters yet

        foreach(char s in source)
        {
            foreach(char c in wantedCharacters) //Is the current illegalChar here in the string?
            {
                if(c == s)
                {
                    if(!capturedCharacters.Contains(c.ToString()))
                        capturedCharacters += c.ToString();  //Send these characters to whoever's asking
                }
            }
        }

        if (capturedCharacters.Length > 0)  
            return true;
        else
            return false;
    }

1
HasWantedCharacters 메서드는 두 개 또는 세 개의 문자열을 허용합니다. 특정 문자를 확인하려는 첫 번째 문자열입니다. 두 번째 문자열, 첫 번째에서 찾을 모든 문자입니다. 오버로드 된 메서드는 세 번째 문자열로 호출자 (예 : Main)에게 출력을 제공합니다. 중첩 된 foreach 문은 소스의 각 문자를 통해 하나씩 비교합니다. 우리가 확인하고있는 캐릭터들과 함께 요. 문자 중 하나가 발견되면 true를 반환합니다. 오버로드 된 메서드는 확인 된 것과 일치하는 문자열을 출력하지만 모두 종료 될 때까지 반환되지 않습니다. 도움이 되셨나요?
Nate Wilkins

1
자유롭게 C # 콘솔 프로젝트를 시작하고 프로그램 클래스 내부의 코드를 복사합니다. main 메서드를 교체해야합니다. 두 문자열 (goodUserName 및 badUserName)을 사용하면 메서드가 수행하는 작업과 작동 방식을 볼 수 있습니다. 예제는 쉼표와 같은 구분 기호없이 수정할 수있는 실행 가능한 솔루션을 제공하기 위해 더 길어졌습니다. 이스케이프 시퀀스는 확인해야 할 경우 작은 따옴표와 백 슬래시를 나타내는 한 가지 방법 일뿐입니다.
Nate Wilkins

1

정규식 을 사용할 수 있습니다.

if(System.Text.RegularExpressions.IsMatch("a|b|c"))

당신은 확실히 할 수 있지만, 거의 모든 것이 더 좋을 때 왜 당신이 원하는지 모르겠습니다.
Steven Sudit

0

문자뿐만 아니라 임의의 문자열을 찾고 있다면 새 프로젝트 NLib 에서 문자열 인수를받는 IndexOfAny 오버로드를 사용할 수 있습니다 .

if (s.IndexOfAny("aaa", "bbb", "ccc", StringComparison.Ordinal) >= 0)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.