web-dev-qa-db-fra.com

Comment comparer les chaînes Unicode en Javascript?

Quand j'ai écrit en JavaScript "Ł" > "Z", il retourne true. Dans l’ordre Unicode, il devrait bien sûr être false. Comment régler ceci? Mon site utilise UTF-8.

36
Tomasz Wysocki

Vous pouvez utiliser Intl.Collator ou String.prototype.localeCompare , introduit par API d'internationalisation ECMAScript :

"Ł".localeCompare("Z", "pl");              // -1
new Intl.Collator("pl").compare("Ł","Z");  // -1

-1 signifie que Ł vient avant Z, comme vous le souhaitez.

Notez que cela ne fonctionne que sur les derniers navigateurs.

27
Oriol

Voici un exemple d'alphabet français qui pourrait vous aider pour un tri personnalisé:

var alpha = function(alphabet, dir, caseSensitive){
  return function(a, b){
    var pos = 0,
      min = Math.min(a.length, b.length);
    dir = dir || 1;
    caseSensitive = caseSensitive || false;
    if(!caseSensitive){
      a = a.toLowerCase();
      b = b.toLowerCase();
    }
    while(a.charAt(pos) === b.charAt(pos) && pos < min){ pos++; }
    return alphabet.indexOf(a.charAt(pos)) > alphabet.indexOf(b.charAt(pos)) ?
      dir:-dir;
  };
};

Pour l'utiliser sur un tableau de chaînes a:

a.sort(
  alpha('ABCDEFGHIJKLMNOPQRSTUVWXYZaàâäbcçdeéèêëfghiïîjklmnñoôöpqrstuûüvwxyÿz')
);

Ajoutez 1 ou -1 comme deuxième paramètre de alpha() pour trier par ordre croissant ou décroissant.
Ajoutez true en tant que troisième paramètre pour trier les données sensibles à la casse.

Vous devrez peut-être ajouter des chiffres et des caractères spéciaux à la liste alphabétique

19
Mic

Vous pourrez peut-être créer votre propre fonction de tri à l'aide de localeCompare() qui - du moins selon l'article article de MDC sur le sujet - devrait trier les choses correctement.

Si cela ne fonctionne pas, voici une intéressante SO question } _ où l'OP utilise le remplacement de chaîne pour créer un mécanisme de tri "brutal-force".

Toujours dans cette question, l'OP montre comment construire une fonction textExtract personnalisée pour le plug-in jQuery tablesorter qui effectue un tri en fonction de la localisation - mérite également un coup d'oeil.

Edit: Comme une idée totalement lointaine - Je ne sais pas du tout si cela est réalisable, en particulier pour des raisons de performances - de toute façon si vous travaillez avec PHP/mySQL sur le back-end, Je voudrais mentionner la possibilité d’envoyer une requête Ajax à une instance mySQL pour la trier ici. MySQL est très efficace pour trier les données tenant compte des paramètres régionaux, car vous pouvez forcer les opérations de tri dans un classement spécifique, par exemple à l'aide de. ORDER BY xyz COLLATE utf8_polish_ci, COLLATE utf8_german_ci.... ces classements prendraient en charge tous les problèmes de tri en même temps.

13
Pekka 웃

Le code de Mic amélioré pour les caractères non mentionnés:

var alpha = function(alphabet, dir, caseSensitive){
  dir = dir || 1;
  function compareLetters(a, b) {
    var ia = alphabet.indexOf(a);
    var ib = alphabet.indexOf(b);
    if(ia === -1 || ib === -1) {
      if(ib !== -1)
        return a > 'a';
      if(ia !== -1)
        return 'a' > b;
      return a > b;
    }
    return ia > ib;
  }
  return function(a, b){
    var pos = 0;
    var min = Math.min(a.length, b.length);
    caseSensitive = caseSensitive || false;
    if(!caseSensitive){
      a = a.toLowerCase();
      b = b.toLowerCase();
    }
    while(a.charAt(pos) === b.charAt(pos) && pos < min){ pos++; }
    return compareLetters(a.charAt(pos), b.charAt(pos)) ? dir:-dir;
  };
};

function assert(bCondition, sErrorMessage) {
      if (!bCondition) {
          throw new Error(sErrorMessage);
      }
}

assert(alpha("bac")("a", "b") === 1, "b is first than a");
assert(alpha("abc")("ac", "a") === 1, "shorter string is first than longer string");
assert(alpha("abc")("1abc", "0abc") === 1, "non-mentioned chars are compared as normal");
assert(alpha("abc")("0abc", "1abc") === -1, "non-mentioned chars are compared as normal [2]");
assert(alpha("abc")("0abc", "bbc") === -1, "non-mentioned chars are compared with mentioned chars in special way");
assert(alpha("abc")("zabc", "abc") === 1, "non-mentioned chars are compared with mentioned chars in special way [2]");
9
Tomasz Wysocki

Vous devez garder deux chaînes de clé de tri. L’un est destiné à l’ordre primaire, où l’allemand ä = a (élément primaire a-> a) et le français é = e (clé de tri primaire e-> e) et l’autre à l’ordre secondaire, où ä vient après un (traduction de a-> azzzz en secondaire touche) ou é vient après e (touche secondaire e-> ezzzz). Surtout en tchèque, certaines lettres sont des variantes d'une lettre (áé…), tandis que d'autres figurent dans leur intégralité (ABCČD… GHChI… RSŠT…). Plus le problème à considérer digraphs une seule lettre (primaire ch-> hzzzz). Pas de problème trivial, et il devrait y avoir une solution au sein de JS.

0
xandru