Rendre HashSet insensible à la casse

J’ai une méthode avec le paramètre HashSet. Et je dois faire la distinction entre les majuscules et les minuscules

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

Est-il possible de rendre HashSet insensible à la casse (ne pas en créer un nouveau)?

Je cherche une solution avec la meilleure performance.

modifier

Contient peut être appelé plusieurs fois. Les extensions IEnumerable ne sont donc pas acceptables en raison des performances inférieures à la méthode HashSet Contains native.

Solution

Puisque la réponse à ma question est NON, c’est impossible, j’ai créé et utilisé la méthode suivante:

 public HashSet EnsureCaseInsensitive(HashSet set) { return set.Comparer == SsortingngComparer.OrdinalIgnoreCase ? set : new HashSet(set, SsortingngComparer.OrdinalIgnoreCase); } 

Le constructeur HashSet a une surcharge qui vous permet de transmettre une IEqualityComparer personnalisée. Certains de ces éléments sont déjà définis pour vous dans la classe SsortingngComparer statique, dont certains ignorent la casse. Par exemple:

 var set = new HashSet(SsortingngComparer.OrdinalIgnoreCase); set.Add("john"); Debug.Assert(set.Contains("JohN")); 

Vous devrez apporter cette modification au moment de la construction du HashSet . Une fois que cela existe, vous ne pouvez pas changer le IEqualityComparer qu’il utilise.


Pour que vous le sachiez, par défaut (si vous ne transmettez pas IEqualityComparer au constructeur HashSet ), il utilise à la place EqualityComparer.Default .


modifier

La question semble avoir changé après avoir posté ma réponse. Si vous devez effectuer une recherche insensible à la casse dans un HashSet sensible à la HashSet existant, vous devrez effectuer une recherche linéaire:

 set.Any(s => ssortingng.Equals(s, item, SsortingngComparison.OrdinalIgnoreCase)); 

Il n’y a pas moyen de contourner cela.

Vous ne pouvez pas faire comme par magie HashSet (ou Dictionary) sensible à la casse pour se comporter de manière insensible à la casse.

Vous devez en recréer un dans votre fonction si vous ne pouvez pas compter sur HashSet entrant pour ne pas faire de HashSet les HashSet et les minuscules.

Code le plus compact – utilisez un constructeur à partir d’un ensemble existant:

 var insensitive = new HashSet( set, SsortingngComparer.InvariantCultureIgnoreCase); 

Notez que la copie de HashSet est aussi chère que de parcourir tous les éléments. Par conséquent, si votre fonction effectue uniquement une recherche, il serait moins coûteux (O (n)) de parcourir tous les éléments. Si votre fonction appelle plusieurs fois pour effectuer une recherche insensible à la casse, essayez HashSet de lui transmettre un HashSet approprié.

Le HashSet est conçu pour trouver rapidement des éléments selon sa fonction de hachage et son comparateur d’égalité. Ce que vous demandez, c’est vraiment de trouver un élément correspondant à «une autre condition». Imaginez que vous ayez un object Set qui utilise uniquement Person.Name pour la comparaison et que vous devez rechercher un élément avec une valeur donnée de Person.Age .

Le point est que vous devez parcourir le contenu de l’ensemble pour trouver les éléments correspondants. Si vous le faites souvent, vous pouvez créer un ensemble différent, dans votre cas, en utilisant un comparateur insensible à la casse, mais vous devrez alors vous assurer que cet ensemble d’ombres est synchronisé avec l’original.

Les réponses à ce jour sont essentiellement des variations de ce qui précède, j’ai pensé à append ceci pour clarifier la question fondamentale.

En supposant que vous avez cette méthode d’extension:

 public static HashSet ToHashSet(this IEnumerable source) { return new HashSet(source); } 

Vous pouvez simplement utiliser ceci:

 set = set.Select(n => n.ToLowerInvariant()).ToHashSet(); 

Ou, vous pourriez juste faire ceci:

 set = new HashSet(set, SsortingngComparer.OrdinalIgnoreCase); //or InvariantCultureIgnoreCase or CurrentCultureIgnoreCase 

Le constructeur de HashSet peut prendre une alternative IEqualityComparer qui peut remplacer la façon dont l’égalité est déterminée. Voir la liste des constructeurs ici .

La classe SsortingngComparer contient un ensemble d’instances statiques de IEqualityComparers pour les chaînes. En particulier, vous êtes probablement intéressé par SsortingngComparer.OrdinalIgnoreCase . Voici la documentation de SsortingngComparer .

Notez qu’un autre constructeur prend un IEnumerable , vous pouvez donc construire un nouveau HashSet partir de votre ancien, mais avec IEqualityComparer .

Donc, tous ensemble, vous voulez convertir votre HashSet comme suit:

 var myNewHashSet = new HashSet(myOldHashSet, SsortingngComparer.OrdinalIgnoreCase); 

Si vous voulez laisser la version originale, sensible à la casse, en place, vous pouvez simplement l’interroger avec linq sans tenir compte de la casse:

 var contains = set.Any(a => a.Equals(item, SsortingngComparison.InvariantCultureIgnoreCase));