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
.
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));