web-dev-qa-db-fra.com

Quelle est la bonne façon de comparer les cas ignorant les caractères?

Je me demande quelle est la bonne façon de comparer deux personnages en ignorant les cas qui fonctionneront dans toutes les cultures. De plus, Comparer<char>.Default est-il le meilleur moyen de tester deux caractères sans ignorer la casse? Cela fonctionne-t-il pour les paires de substitution?

EDIT: Exemple de mise en oeuvre de IComparer<char>

Si cela aide quelqu'un, voici ce que j'ai décidé d'utiliser

public class CaseInsensitiveCharComparer : IComparer<char> {
    private readonly System.Globalization.CultureInfo ci;
    public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
        this.ci = ci;
    }
    public CaseInsensitiveCharComparer()
        : this(System.Globalization.CultureInfo.CurrentCulture) { }
    public int Compare(char x, char y) {
        return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
    }
}

// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
46
Brett Ryan

Cela dépend de ce que vous entendez par "travailler pour toutes les cultures". Voudriez-vous que "je" et "je" soient égaux, même en Turquie?

Vous pouvez utiliser:

bool equal = char.ToUpperInvariant(x) == char.ToUpperInvariant(y);

... mais je ne suis pas sûr que cela "fonctionne" selon toutes les cultures par votre compréhension de "travaux".

Bien sûr, vous pouvez convertir les deux caractères en chaînes, puis effectuer la comparaison souhaitée sur les chaînes. Un peu moins efficace, mais cela vous donne toute la gamme des comparaisons disponibles dans le cadre:

bool equal = x.ToString().Equals(y.ToString(), 
                                 StringComparison.InvariantCultureIgnoreCase);

Pour les paires de substitution, un Comparer<char> ne sera de toute façon pas réalisable, car vous n'avez pas une seule char. Vous pouvez cependant créer un Comparer<int>.

78
Jon Skeet

Utilisation de la culture par défaut (c'est-à-dire pas l'invariant): 

if (char.ToLower(ch1) == char.ToLower(ch2))
{  ....  }

Ou spécifiez une culture:

CultureInfo myCulture = ...;
if (char.ToLower(ch1, myCulture) == char.ToLower(ch2, myCulture))
{  ....  }
13
Henk Holterman

Si je comprends bien, il n’ya pas vraiment de moyen de "fonctionner pour toutes les cultures". Soit vous voulez comparer des caractères pour une sorte de raison interne non affichée à l'utilisateur (auquel cas vous devez utiliser InvariantCulture), ou vous voulez utiliser le CurrentCulture de l'utilisateur. Évidemment, en utilisant la culture actuelle de l'utilisateur, vous obtiendrez des résultats différents selon les paramètres régionaux, mais ils seront cohérents avec les attentes de vos utilisateurs dans ces paramètres.

Sans en savoir plus sur POURQUOI vous comparez deux personnages, je ne peux pas vraiment vous conseiller sur celui que vous devriez utiliser. 

2
Jon Grant

string.Compare ("string a", "STRING A", true)

Cela fonctionnera pour chaque corde

1
Sergio

Ce que je pensais être disponible dans le runtime ressemble à ceci

public class CaseInsensitiveCharComparer : IComparer<char> {
    private readonly System.Globalization.CultureInfo ci;
    public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
        this.ci = ci;
    }
    public CaseInsensitiveCharComparer()
        : this(System.Globalization.CultureInfo.CurrentCulture) { }
    public int Compare(char x, char y) {
        return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
    }
}

// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
0
Brett Ryan

Je recommande de comparer les majuscules, et si elles ne correspondent pas, comparez les minuscules, juste au cas où la logique de majuscules et de minuscules de la région se comporterait légèrement différemment.

Addenda

Par exemple,

int CompareChar(char c1, char c2)
{
    int  dif;

    dif = char.ToUpper(c1) - char.ToUpper(c2);
    if (diff != 0)
        dif = char.ToLower(c1) - char.ToLower(c2);
    return dif;
}
0
David R Tribble

Tu pourrais essayer:

    class Test{
    static int Compare(char t, char p){
        return string.Compare(t.ToString(), p.ToString(), StringComparison.CurrentCultureIgnoreCase);
    }
}

Mais je doute que ce soit la manière "optimale" de le faire, mais je ne suis pas dans tous les cas à vérifier ...

0
ahawker