[C#] 대소 문자를 구분하지 않는 목록 검색

testList많은 문자열을 포함 하는 목록 이 있습니다. testList목록에없는 경우에만 새 문자열을 추가하고 싶습니다 . 따라서 대소 문자를 구분하지 않고 목록을 검색하고 효율적으로 만들어야합니다. Contains케이스를 고려하지 않기 때문에 사용할 수 없습니다 . 또한 ToUpper/ToLower성능상의 이유로 사용하고 싶지 않습니다 . 나는이 방법을 발견했다.

    if(testList.FindAll(x => x.IndexOf(keyword,
                       StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
       Console.WriteLine("Found in list");

이것은 작동하지만 부분 단어와도 일치합니다. 목록에 “염소”가 포함되어 있으면 “귀리”가 이미 목록에 있다고 주장하기 때문에 “귀리”를 추가 할 수 없습니다. 단어가 정확히 일치해야하는 대소 문자를 구분하지 않는 방식으로 목록을 효율적으로 검색하는 방법이 있습니까? 감사



답변

String.IndexOf 대신 String.Equals 를 사용 하여 부분 일치가 없는지 확인하십시오. 또한 모든 요소를 ​​통과하는 FindAll을 사용하지 말고 FindIndex를 사용 하십시오 (첫 번째 요소는 중지합니다).

if(testList.FindIndex(x => x.Equals(keyword,
    StringComparison.OrdinalIgnoreCase) ) != -1)
    Console.WriteLine("Found in list"); 

또는 일부 LINQ 방법을 사용하십시오 (첫 번째 방법에서도 중지됨)

if( testList.Any( s => s.Equals(keyword, StringComparison.OrdinalIgnoreCase) ) )
    Console.WriteLine("found in list");


답변

나는 이것이 오래된 게시물이라는 것을 알고 있지만 다른 사람이 찾고 있는 경우를 대비하여 대소 문자를 구분하지 않는 문자열 동등 비교기를 제공하여 사용할 있습니다 Contains.

using System.Linq;

// ...

if (testList.Contains(keyword, StringComparer.OrdinalIgnoreCase))
{
    Console.WriteLine("Keyword Exists");
}

이것은 msdn 에 따라 .net 2.0부터 사용 가능 합니다.


답변

위의 Adam Sills 답변을 기반으로-Contains … 🙂

///----------------------------------------------------------------------
/// <summary>
/// Determines whether the specified list contains the matching string value
/// </summary>
/// <param name="list">The list.</param>
/// <param name="value">The value to match.</param>
/// <param name="ignoreCase">if set to <c>true</c> the case is ignored.</param>
/// <returns>
///   <c>true</c> if the specified list contais the matching string; otherwise, <c>false</c>.
/// </returns>
///----------------------------------------------------------------------
public static bool Contains(this List<string> list, string value, bool ignoreCase = false)
{
    return ignoreCase ?
        list.Any(s => s.Equals(value, StringComparison.OrdinalIgnoreCase)) :
        list.Contains(value);
}


답변

StringComparer를 사용할 수 있습니다 :

    var list = new List<string>();
    list.Add("cat");
    list.Add("dog");
    list.Add("moth");

    if (list.Contains("MOTH", StringComparer.OrdinalIgnoreCase))
    {
        Console.WriteLine("found");
    }


답변

랜스 라슨 (Lance Larsen) 답변을 기반으로-권장 문자열이있는 확장 방법이 있습니다. 문자열 대신 비교하십시오.

StringComparison 매개 변수를 사용하는 String.Compare의 오버로드를 사용하는 것이 좋습니다. 이러한 오버로드를 통해 의도 한 정확한 비교 동작을 정의 할 수있을뿐만 아니라이를 사용하면 다른 개발자가 코드를보다 쉽게 ​​읽을 수 있습니다. [ 조쉬 프리 @ BCL 팀 블로그 ]

public static bool Contains(this List<string> source, string toCheck, StringComparison comp)
{
    return
       source != null &&
       !string.IsNullOrEmpty(toCheck) &&
       source.Any(x => string.Compare(x, toCheck, comp) == 0);
}


답변

IndexOf의 결과가 0보다 크거나 같은지 여부를 확인 중 입니다. 즉, 문자열의 어느 곳에서나 일치가 시작되는지 여부를 의미합니다 . 0 과 같은지 확인하십시오 .

if (testList.FindAll(x => x.IndexOf(keyword,
                   StringComparison.OrdinalIgnoreCase) >= 0).Count > 0)
   Console.WriteLine("Found in list");

이제 “염소”와 “귀리”는 일치하지 않지만 “염소”와 “고아”는 일치합니다. 이를 피하기 위해 두 줄의 길이를 비교할 수 있습니다.

이 모든 합병증을 피하기 위해 목록 대신 사전을 사용할 수 있습니다. 키는 소문자 문자열이고 값은 실제 문자열입니다. 이렇게하면 ToLower각 비교 에 사용할 필요 가 없기 때문에 성능이 저하되지 않지만 여전히을 사용할 수 있습니다 Contains.


답변

아래는 전체 목록에서 키워드를 검색하고 해당 항목을 제거하는 예입니다.

public class Book
{
  public int BookId { get; set; }
  public DateTime CreatedDate { get; set; }
  public string Text { get; set; }
  public string Autor { get; set; }
  public string Source { get; set; }
}

Text 속성에 키워드가 포함 된 책을 제거하려면 키워드 목록을 만들어 책 목록에서 제거 할 수 있습니다.

List<Book> listToSearch = new List<Book>()
   {
        new Book(){
            BookId = 1,
            CreatedDate = new DateTime(2014, 5, 27),
            Text = " test voprivreda...",
            Autor = "abc",
            Source = "SSSS"

        },
        new Book(){
            BookId = 2,
            CreatedDate = new DateTime(2014, 5, 27),
            Text = "here you go...",
            Autor = "bcd",
            Source = "SSSS"


        }
    };

var blackList = new List<string>()
            {
                "test", "b"
            };

foreach (var itemtoremove in blackList)
    {
        listToSearch.RemoveAll(p => p.Source.ToLower().Contains(itemtoremove.ToLower()) || p.Source.ToLower().Contains(itemtoremove.ToLower()));
    }


return listToSearch.ToList();