web-dev-qa-db-fra.com

Comment comparer les caractères ignorant la casse dans les types primitifs

J'écris ces lignes de code:

String name1 = fname.getText().toString();
String name2 = sname.getText().toString();
aru = 0;

count1 = name1.length();
count2 = name2.length();
for (i = 0; i < count1; i++)
{  
    for (j = 0; j < count2; j++)
    { 
        if (name1.charAt(i)==name2.charAt(j))
            aru++;
    }
    if(aru!=0)
        aru++;
}

Je veux comparer la Characters de deux Strings ignorant le cas. Utiliser simplement IgnoreCase ne fonctionne pas. L'ajout de '65' ASCII value ne fonctionne pas non plus. Comment puis-je faire cela?

19
Arush Kamboj

La classe Character de l'API Java comporte diverses fonctions que vous pouvez utiliser.

Vous pouvez convertir votre caractère en minuscule des deux côtés:

Character.toLowerCase(name1.charAt(i)) == Character.toLowerCase(name2.charAt(j))

Vous pouvez également utiliser une méthode pour vérifier si la lettre est en majuscule ou en minuscule:

Character.isUpperCase('P')
Character.isLowerCase('P') 
36
Shehzad

Vous ne pouvez pas réellement faire le travail correctement avec toLowerCase, que ce soit sur une chaîne ou dans un caractère. Le problème est qu’il existe des variantes de glyphes en majuscules ou en minuscules, et selon que vous soyez en majuscule ou en minuscule, vos glyphes peuvent être préservés ou non. On ne sait même pas ce que vous moyenne quand vous dites que deux variantes d'un glyphe minuscule sont comparées sans tenir compte des cas: sont-elles ou ne sont-elles pas identiques? (Notez qu'il existe également des glyphes à casse mixte: \u01c5, \u01c8, \u01cb, \u01f2 ou Dž, Lj, Nj, Dz, mais toute méthode suggérée ici fonctionnera aussi longtemps qu'ils seront considérés comme identiques.)

Il existe un problème supplémentaire lié à l'utilisation de Char: il existe environ 80 points de code non représentables avec un seul Char qui sont des variantes majuscules/minuscules (40 de chaque), du moins tels qu'ils ont été détectés par les majuscules/minuscules de Java. Vous devez donc obtenir les points de code et changer la casse de ceux-ci.

Mais les points de code ne vous aident pas avec les variantes de glyphes.

Quoi qu'il en soit, voici une liste complète des glyphes qui posent problème en raison des variantes, en montrant comment ils se débrouillent par rapport à 6 méthodes différentes:

  1. Caractère toLowerCase
  2. Caractère toUpperCase
  3. Chaîne toLowerCase
  4. Chaîne toUpperCase
  5. Chaîne equalsIgnoreCase
  6. Caractère toLowerCase(toUpperCase) (ou vice versa)

Pour ces méthodes, S signifie que les variantes sont traitées de la même façon, D signifie que les variantes sont traitées de manière différente.

Behavior     Unicode                             Glyphs
===========  ==================================  =========
1 2 3 4 5 6  Upper  Lower  Var Up Var Lo Vr Lo2  U L u l l2
- - - - - -  ------ ------ ------ ------ ------  - - - - -
D D D D S S  \u0049 \u0069 \u0130 \u0131         I i İ ı   
S D S D S S  \u004b \u006b \u212a                K k K     
D S D S S S  \u0053 \u0073        \u017f         S s   ſ   
D S D S S S  \u039c \u03bc        \u00b5         Μ μ   µ   
S D S D S S  \u00c5 \u00e5 \u212b                Å å Å     
D S D S S S  \u0399 \u03b9        \u0345 \u1fbe  Ι ι   ͅ ι 
D S D S S S  \u0392 \u03b2        \u03d0         Β β   ϐ   
D S D S S S  \u0395 \u03b5        \u03f5         Ε ε   ϵ   
D D D D S S  \u0398 \u03b8 \u03f4 \u03d1         Θ θ ϴ ϑ   
D S D S S S  \u039a \u03ba        \u03f0         Κ κ   ϰ   
D S D S S S  \u03a0 \u03c0        \u03d6         Π π   ϖ   
D S D S S S  \u03a1 \u03c1        \u03f1         Ρ ρ   ϱ   
D S D S S S  \u03a3 \u03c3        \u03c2         Σ σ   ς   
D S D S S S  \u03a6 \u03c6        \u03d5         Φ φ   ϕ   
S D S D S S  \u03a9 \u03c9 \u2126                Ω ω Ω     
D S D S S S  \u1e60 \u1e61        \u1e9b         Ṡ ṡ   ẛ   

Ce qui complique encore les choses, c’est qu’il n’ya aucun moyen d’obtenir le droit en turc (c’est-à-dire que les versions en pointillé sont différentes des versions sans points) sauf si vous savez que vous êtes en turc; Aucune de ces méthodes ne donne un comportement correct et ne peut pas si vous ne connaissez pas les paramètres régionaux (c'est-à-dire non-turc: i et I sont les mêmes cas ignorants; turc, pas).

Dans l’ensemble, utiliser toUpperCase vous donne l’approximation la plus proche, puisque vous n’avez que cinq variantes majuscules (ou quatre, sans compter le turc).

Vous pouvez également essayer d’intercepter spécifiquement ces cinq cas problématiques et d’appeler toUpperCase(toLowerCase(c)) uniquement. Si vous choisissez vos gardes avec précaution (juste toUpperCase si c < 0x130 || c > 0x212B, alors travaillez avec les autres alternatives), vous ne pouvez obtenir qu'une pénalité de vitesse d'environ 20% pour les caractères de la plage inférieure (par rapport à ~ 4x si vous convertissez des caractères uniques en chaînes et equalsIgnoreCase eux et seulement environ une pénalité de 2x si vous avez beaucoup dans la zone de danger. Vous avez toujours le problème de paramètres régionaux avec I en pointillé, mais sinon vous êtes en forme. Bien sûr, si vous pouvez utiliser equalsIgnoreCase sur une chaîne plus grande, vous feriez mieux de le faire.

Voici un exemple de code Scala qui fait le travail:

def elevateCase(c: Char): Char = {
  if (c < 0x130 || c > 0x212B) Character.toUpperCase(c)
  else if (c == 0x130 || c == 0x3F4 || c == 0x2126 || c >= 0x212A)
    Character.toUpperCase(Character.toLowerCase(c))
  else Character.toUpperCase(c)
}
12
Rex Kerr

Vous pouvez changer la casse de String avant de l'utiliser, comme ceci

String name1 = fname.getText().toString().toLowerCase(); 
String name2 = sname.getText().toString().toLowerCase();

Continuez ensuite avec l'opération de repos.

7
Azhar Shaikh

Vous pouvez mettez les deux caractères en minuscule puis comparez-les.

4
assylias

Vous devez tenir compte du problème turc I lorsque vous comparez des caractères/des minuscules/majuscules:

Je suggère de convertir en chaîne et d'utiliser toLowerCase avec une culture invariante (du moins dans la plupart des cas).

public statique final public InvariantLocale = new Locale (Empty, Empty, Empty); str.toLowerCase (InvariantLocale)

Voir un C # similaire string.ToLower () and string.ToLowerInvariant ()

Remarque: n'utilisez pas String.equalsIgnoreCase http://nikolajlindberg.blogspot.co.il/2008/03/beware-of-Java-comparing-turkish.html

2
Dekel

Méthodes génériques pour comparer un caractère situé entre 2 chaînes avec la casse ignorée.

public static boolean isEqualIngoreCase(char one, char two){
    return Character.toLowerCase(one)==Character .toLowerCase(two);
}

public static boolean isEqualStringCharIgnoreCase(String one, String two, int position){
    char oneChar = one.charAt(position);
    char twoChar = two.charAt(position);
    return isEqualIngoreCase(oneChar, twoChar);
}

Appel de fonction

boolean isFirstCharEqual = isEqualStringCharIgnoreCase("abc", "ABC", 0)
0
Siddarth Kanted

Voici comment le JDK le fait (adapté de OpenJDK 8, String.Java/regionMatches ):

static boolean charactersEqualIgnoringCase(char c1, char c2) {
  if (c1 == c2) return true;

  // If characters don't match but case may be ignored,
  // try converting both characters to uppercase.
  char u1 = Character.toUpperCase(c1);
  char u2 = Character.toUpperCase(c2);
  if (u1 == u2) return true;

  // Unfortunately, conversion to uppercase does not work properly
  // for the Georgian alphabet, which has strange rules about case
  // conversion.  So we need to make one last check before
  // exiting.
  return Character.toLowerCase(u1) == Character.toLowerCase(u2);
}

Je suppose que ça marche aussi pour le turc?

0
Stefan Reich