1. ホーム
  2. c#

[解決済み] HashSet<string>の大文字と小文字を区別しない機能

2023-04-13 05:30:22

質問

HashSetパラメータを持つメソッドを持っています。そして、私はその中で大文字と小文字を区別しないContainsを行う必要があります。

public void DoSomething(HashSet<string> set, string item)
{
    var x = set.Contains(item);
    ... 
}

既存のHashSetを大文字小文字を区別しない(新規に作成しない)ようにする方法はありますか?

最高のパフォーマンスで解決する方法を探しています。

編集

Containsは複数回呼び出すことができます。そのため、IEnumerableの拡張は、ネイティブのHashSet Containsメソッドよりもパフォーマンスが低いため、私には受け入れられません。

解決方法

質問に対する答えは「NO」であり、不可能です。

public HashSet<string> EnsureCaseInsensitive(HashSet<string> set)
{
    return set.Comparer == StringComparer.OrdinalIgnoreCase
           ? set
           : new HashSet<string>(set, StringComparer.OrdinalIgnoreCase);
}

どのように解決するのですか?

この HashSet<T> コンストラクタにはオーバーロードがあり、独自の IEqualityComparer<string> . これらのうちいくつかは、すでに静的な StringComparer クラスで定義されており、そのうちのいくつかは大文字小文字を無視します。例えば

var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
set.Add("john");
Debug.Assert(set.Contains("JohN"));

を構築する際に、この変更を行う必要があります。 HashSet<T> . いったん存在すると IEqualityComparer<T> を変更することはできません。


念のためお伝えしておきますが、デフォルトでは (何も渡さなければ) IEqualityComparer<T>HashSet<T> のコンストラクタ) を使用する場合、それは EqualityComparer<T>.Default を使います。


編集

私が回答を投稿した後、質問が変更されたようです。 もし、ケース を無視する を行う必要がある場合、既存のケース センシティブ HashSet<string> のように、線形探索を行う必要があります。

set.Any(s => string.Equals(s, item, StringComparison.OrdinalIgnoreCase));

これを回避する方法はない。