programing

문자열에 목록의 요소가 포함되어 있는지 확인합니다.

newstyles 2023. 5. 29. 09:56

문자열에 목록의 요소가 포함되어 있는지 확인합니다.

다음 코드 블록의 경우:

For I = 0 To listOfStrings.Count - 1
    If myString.Contains(lstOfStrings.Item(I)) Then
        Return True
    End If
Next
Return False

출력은 다음과 같습니다.

사례 1:

myString: C:\Files\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: True

사례 2:

myString: C:\Files3\myfile.doc
listOfString: C:\Files\, C:\Files2\
Result: False

목록(listOfStrings)은 여러 항목(최소 20개)을 포함할 수 있으며 수천 개의 문자열(myString과 같은)에 대해 확인해야 합니다.

이 코드를 더 효율적으로 작성할 수 있는 방법이 있습니까?

LINQ와 C#을 사용하는 경우(요즘은 VB를 잘 모릅니다.

bool b = listOfStrings.Any(s=>myString.Contains(s));

또는 (더 빠르고 더 효율적이지만 분명 덜 명확함):

bool b = listOfStrings.Any(myString.Contains);

만약 당신이 평등을 테스트하고 있다면, 그것은 볼 가치가 있을 것입니다.HashSet등입니다. 그러나 이것은 조각으로 나누고 복잡성 순서를 추가하지 않는 한 부분 일치에는 도움이 되지 않습니다.


update:로 "StartsWith"를한다면, 할 수 . update: 만약당신정를이말로면한 "StartsWith"의미다당다신니은, 그을목고정배배열로렬하치수할있록다사니합나용습서리고▁update▁update:; :▁and▁;▁if다▁list니▁sort사합나▁array용start서,▁then▁you▁"리그고"▁then▁an▁it▁mean▁use만▁really▁you▁could;다니있▁the▁into▁place습start수약s치할열렬배를하Array.BinarySearch각 항목 찾기 - 전체 또는 부분 일치 여부를 조회하여 확인합니다.

당신이 당신의 끈을 구성할 때는 이렇게 되어야 합니다.

bool inact = new string[] { "SUSPENDARE", "DIZOLVARE" }.Any(s=>stare.Contains(s));

저는 마크의 답변이 마음에 들었지만 CaSe InSenSiTiVe가 되기 위해서 Contains 매칭이 필요했습니다.

이것이 해결책이었습니다.

bool b = listOfStrings.Any(s => myString.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0))

이전의 유사한 질문 "많은 비교 가능한 목록에 대해 기존 문자열을 테스트하는 가장 좋은 방법"에서 많은 제안이 있었습니다.

Regex로 충분할 수 있습니다. 모든 서브스트링의이며 OR "은모든후서연입며결이의은다링식트니스브보▁or은", 또는 "입▁"다니▁the,며▁beion▁express"로 됩니다.|그들 사이의 연산자.물론 표현식을 작성할 때 이스케이프되지 않은 문자를 주의해야 하거나 복잡성이나 크기 제한으로 인해 컴파일에 실패해야 합니다.

이를 위한 또 다른 방법은 모든 후보 하위 문자열을 나타내는 트라이 데이터 구조를 구성하는 것입니다(이것은 정규식 매칭기가 수행하는 것을 다소 복제할 수 있습니다).테스트 문자열의 각 문자를 단계적으로 통과할 때 트리의 루트에 대한 새 포인터를 만들고 기존 포인터가 있는 경우 해당 자식 포인터로 이동합니다.어떤 포인터가 잎에 닿으면 일치하는 것을 얻을 수 있습니다.

오래된 질문.하지만 그 이후로VB.NET원래 요구 사항이었습니다.허용된 답변의 동일한 값 사용:

listOfStrings.Any(Function(s) myString.Contains(s))

목록에 있는 항목이 (긴) 문자열에 있는지 확인해야 했기 때문에 다음과 같은 항목을 선택했습니다.

listOfStrings.Any(x => myString.ToUpper().Contains(x.ToUpper()));

또는 vb.net 에서:

listOfStrings.Any(Function(x) myString.ToUpper().Contains(x.ToUpper()))

패턴에 따라 Contains 대신 StartsWith를 사용하는 것으로 변경할 수 있습니다.첫 번째 불일치를 찾을 때마다 모든 문자 위치에서 검색을 다시 시작하지 않고 첫 번째 불일치를 찾을 때까지 각 문자열을 반복해야 합니다.

또한 패턴에 따라 myString 경로의 첫 번째 부분을 추출한 다음 비교를 반대로 할 수 있습니다. 문자열 목록에서 myString의 시작 경로를 찾는 것이 아니라 문자열 목록에서 myString의 시작 경로를 찾는 것입니다.

string[] pathComponents = myString.Split( Path.DirectorySeparatorChar );
string startPath = pathComponents[0] + Path.DirectorySeparatorChar;

return listOfStrings.Contains( startPath );

편집: 변경할 수 있으므로 @Marc Gravell이 언급한 해시셋 아이디어를 사용하는 것이 훨씬 빠를 입니다.Contains로.ContainsKey조회는 O(N) 대신 O(1)입니다.경로가 정확히 일치하는지 확인해야 합니다.이것은 @Marc Gravell과 같은 일반적인 해결책이 아니라 사용자의 예에 맞게 조정된 것입니다.

C# 예를 들어 죄송합니다.저는 VB로 번역할 만큼 충분한 커피를 마시지 못했습니다.

속도를 테스트해 보셨습니까?

예: 샘플 데이터 세트를 생성하고 프로파일링했습니까?당신이 생각하는 것만큼 나쁘지 않을 수도 있습니다.

이것은 또한 여러분이 별도의 실에 산란하여 속도의 환상을 줄 수 있는 것일 수 있습니다!

myList.Any(myString.Contains);

의 단점은Contains방법은 문자열을 비교할 때 종종 중요한 비교 유형을 지정할 수 없다는 것입니다.그것은 항상 문화와 대소문자를 구분합니다.그래서 저는 WhoIsRich의 답은 가치가 있다고 생각합니다. 저는 단지 더 간단한 대안을 보여주고 싶습니다.

listOfStrings.Any(s => s.Equals(myString, StringComparison.OrdinalIgnoreCase))

속도가 중요한 경우 패턴 집합에 대한 Aho-Corasick 알고리즘을 찾는 것이 좋습니다.

오류 링크가 있는 시도입니다. 즉, 복잡도는 O(n+m+k)입니다. 여기서 n은 입력 텍스트의 길이, m은 패턴의 누적 길이 및 k 일치 수입니다.첫 번째 일치 항목이 발견된 후 종료되도록 알고리즘을 수정하면 됩니다.

약간의 변화, 저는 문자열에 전체 단어와 대소문자를 구분하지 않는 것이 있는지 확인해야 했습니다.

myString.Split(' ', StringSplitOptions.RemoveEmptyEntries).Intersect(listOfStrings).Any())

대소문자를 구분하지 않는 경우myString그리고.listOfStrings대문자로 변환되었습니다.

언급URL : https://stackoverflow.com/questions/500925/check-if-a-string-contains-an-element-from-a-list-of-strings