web-dev-qa-db-ja.com

大文字と小文字を区別しないリスト検索

文字列の束を含むリストtestListがあります。リストにまだ存在しない場合にのみ、testListに新しい文字列を追加したいと思います。したがって、大文字と小文字を区別せずにリストを検索し、効率的にする必要があります。 Containsを使用できません。これは、大文字と小文字を考慮しないためです。また、パフォーマンス上の理由でToUpper/ToLowerを使いたくありません。私はこの方法に出会いましたが、それは機能します:

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

これは機能しますが、部分的な単語にも一致します。リストに「goat」が含まれている場合、「oat」はすでにリストにあると主張するため、「oat」を追加できません。大文字と小文字を区別しない方法でリストを効率的に検索する方法はありますか?ありがとう

118
Brap

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");
151
Adam Sills

私はこれが古い投稿であることを理解していますが、他の誰かが探している場合に備えて、あなたはcan大文字と小文字を区別しない文字列の同等性を提供することでContainsを使用しますそのような比較器:

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

これは、 msdn に従って.net 2.0以降で利用可能です。

305
shaxby

上記の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");
    }
4
jlo-gmail

Lance Larsenの答えに基づいて-ここでは、string.Equalsの代わりに推奨string.Compareを使用した拡張メソッドがあります

StringComparisonパラメーターを受け取るString.Compareのオーバーロードを使用することを強くお勧めします。これらのオーバーロードを使用すると、意図したとおりの正確な比較動作を定義できるようになるだけでなく、他の開発者がコードを読みやすくすることもできます。 [ Josh Free @ BCL Team Blog ]

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

私は同様の問題を抱えていました、アイテムのインデックスが必要でしたが、大文字と小文字を区別しない必要があり、数分間ウェブを見て回りましたが、何も見つかりませんでしたので、それを実現するための小さなメソッドを書いただけですした:

private static int getCaseInvariantIndex(List<string> ItemsList, string searchItem)
{
    List<string> lowercaselist = new List<string>();

    foreach (string item in ItemsList)
    {
        lowercaselist.Add(item.ToLower());
    }

    return lowercaselist.IndexOf(searchItem.ToLower());
}

このコードを同じファイルに追加し、次のように呼び出します。

int index = getCaseInvariantIndexFromList(ListOfItems, itemToFind);

これがお役に立てば幸いです!

0

IndexOfの結果が0以上かどうか、つまり文字列内で一致がanywhereで始まるかどうかをチェックしています。 equal to 0かどうかを確認してください:

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

現在、「ヤギ」と「オーツ」は一致しませんが、「ヤギ」と「ゴア」は一致します。これを避けるために、2つの文字列の長さを比較できます。

このすべての複雑さを避けるために、リストの代わりに辞書を使用できます。キーは小文字の文字列になり、値は実際の文字列になります。この方法では、各比較にToLowerを使用する必要がないため、パフォーマンスは低下しませんが、Containsを使用できます。

0
Ilya Kogan