2015-03-10 2 views
5

testés dans le dernier Firefox et Chrome (qui ont une locale « de » sur mon système):localeCompare montre un comportement incohérent lors du tri des mots avec les principaux personnages umlaut

"Ä".localeCompare("A") 

me donne 1, ce qui signifie qu'il croit "Ä" devrait apparaissent après"A" dans un ordre trié, ce qui est correct.

Mais:

"Ägypten".localeCompare("Algerien") 

me donne -1, ce qui signifie qu'il croit "Ägypten" devrait apparaître avant"Algerien" dans un ordre de tri.

Pourquoi? Pourquoi regarde-t-il au-delà du premier caractère de chaque chaîne, si elle dit que le premier caractère de la première chaîne devrait apparaître après le premier caractère de la deuxième chaîne quand vous le contrôlez seul?

Répondre

1

Ici vous avez la méthode juste pour vos besoins, copier-coller cette méthode:

analyse syntaxique récursif de chaînes et donner lieu ombles comparer les résultats liez pas :)

RÉSULTAT FINAL Correction d'un bug, ajouté comparer (arrêt incorrect ou boucle récursive) à des chaînes entières:

String.prototype.MylocaleCompare = function (right, idx){ 
    idx = (idx == undefined) ? 0 : idx++; 

    var run = right.length <= this.length ? (idx < right.length - 1 ? true : false) : (idx < this.length - 1 ? true : false); 


    if (!run) 
    { 
     if (this[0].localeCompare(right[0]) == 0) 
      { 
       return this.localeCompare(right); 
      } 
      else 
      { 
       return this[0].localeCompare(right[0]) 
      } 
    } 

    if(this.localeCompare(right) != this[0].localeCompare(right[0])) 
    { 
     var myLeft = this.slice(1, this.length); 
     var myRight = right.slice(1, right.length); 
     if (myLeft.localeCompare(myRight) != myLeft[0].localeCompare(myRight[0])) 
     { 
      return myLeft.MylocaleCompare(myRight, idx); 
     } 
     else 
     { 
      if (this[0].localeCompare(right[0]) == 0) 
      { 
       return myLeft.MylocaleCompare(myRight, idx); 
      } 
      else 
      { 
       return this[0].localeCompare(right[0]) 
      } 
     } 
    } 
    else 
    { 
     return this.localeCompare(right); 
    } 

} 
+0

Votre algorithme semble fonctionner, l'avez-vous programmé vous-même ou l'avez-vous quelque part? – wnstnsmth

+0

@wnstnsmth Je l'ai programmé moi-même, mais ce n'est pas complètement fonctionnel (mon mauvais ici), j'espère trouver le temps de le réparer aujourd'hui, ou demain je reviendrai avec le correctif :) – SilentTremor

+0

Ouais, j'ai trouvé un bug : Si la chaîne a est un sous-ensemble de la chaîne b, comme ceci (a === "Indien", b === "Indien (CA)"), alors Firefox lance une erreur que myLeft [0] n'est pas définie. – wnstnsmth

1

http://en.wikipedia.org/wiki/Diaeresis_(diacritic)#Printing_conventions_in_German

« Lorsque par ordre alphabétique trier les mots allemands, le tréma est généralement pas distingué de la voyelle sous-jacente, bien que si deux mots ne diffèrent que par un tréma, celui tréma arrive en deuxième position [...]
« Il y a un deuxième système en cours d'utilisation limitée, la plupart du temps pour les noms de tri (appelés familièrement « l'annuaire téléphonique de tri »), qui traite ü comme ue, et ainsi de suite. »

en supposant que le s type d'algorithme de tri est appliqué, alors les résultats que vous voyez ont un sens.

Ä deviendrait Ae, et qui est « plus », votre autre valeur A, le tri si A avant Ae et à cet effet A avant Ä serait correct (et comme vous l'avez dit, vous considérez que ce soit correct, et même par le premier algorithme qui traite seulement Ä comme A ce serait correct, aussi).

maintenant Ägypten devient Aegypten à des fins de tri, et par conséquent, il doit comparaître devant Algerien dans la même logique de tri - les premières lettres des deux termes sont égaux, il est aux seconds pour déterminer l'ordre de tri, et e a une valeur de tri lexicographique inférieure à l. Par conséquent, Aegypten avant Algerien, ce qui signifie Ägypten avant Algerien.


Wikipedia allemand développe encore plus sur ce (http://de.wikipedia.org/wiki/Alphabetische_Sortierung#Einsortierungsregeln_f.C3.BCr_weitere_Buchstaben), et note qu'il existe deux variantes du DIN pertinentes 5007.

DIN 5007 variante 1 dit, ä doit être traité comme a, ö comme o et ü comme u, et que ce type de tri devait être utilisé pour les dictionnaires et similaires.

La variante 1 de la norme DIN 5007 dit l'autre chose, ä pour être traitée comme ae, etc., et cela doit être utilisé principalement pour les listes de noms tels que les annuaires téléphoniques.

Wikipédia poursuit en disant que cela prend en compte qu'il pourrait y avoir plus d'une forme de l'orthographe des noms de personnes (peut-être Moeller ou Möller, les deux versions existent Nom de quelqu'un), alors que pour les mots un dictionnaire il n'y a habituellement que un l'orthographe qui est considéré comme correct. Maintenant, je pense que la question de prix restante est: Puis-je demander aux navigateurs d'appliquer l'autre forme de tri pour les paramètres régionaux allemands? Pour être franc, je ne sais pas.

Il pourrait sûrement être souhaitable de pouvoir choisir entre ces deux formes de tri, parce que Wikipedia dit les noms personnels Moeller et Möller existent, mais il n'y a que Ägypten et non Aegypten quand ça vient à un dictionnaire.

+0

Cela a du sens, MAIS, il y a cette chose. Quand je fais '[" Ä "," A "]. Sort();' et '['Ägypten', 'Algerien']. Sort();' j'obtiens des résultats égaux - l'umlaut vient en second, donc il semble qu'il y ait est une sorte d'erreur à l'intérieur de 'compareLocale' après tout. ' – Eternal1

+1

@ Eternal1:' Array.sort' n'est pas sensible aux paramètres régionaux, de sorte que les règles de comparaison de chaînes "normales" seront appliquées. Et puisque les chaînes n'ont pas une méthode 'compare' simple, je suppose que cela se produit sur la base de valeurs d'octets, pas de caractères. – CBroe

+0

Merci pour cette réponse élaborée. Je me demande si l'implémentation de localeCompare est documentée quelque part. Je pensais qu'il ferait une comparaison unicode caractère par caractère, et ne pas convertir "ä" en "ae" d'abord comme dans la variante DIN5007 2. Ce qui n'a pas beaucoup de sens à mes yeux. – wnstnsmth