Efficacement remplacer tous les caractères accentués dans une chaîne de caractères?
Pour un homme pauvre de la mise en œuvre de près de-classement-tri correct sur le côté client, j'ai besoin d'une fonction JavaScript qui ne efficace seul remplacement de caractères dans une chaîne.
Voici ce que je veux dire (notez que cela s'applique au texte allemand, autres langues trier différemment):
natif de tri s'il se trompe: a b c o u z ä ö ü classement correct serait: un ä b c o ö u ü z
En gros, j'ai besoin de toutes les occurrences de "ä" d'une chaîne donnée remplacé par "a" (et ainsi de suite). De cette façon, le résultat de natif de tri serait très proche de ce qu'un utilisateur pourrait s'attendre (ou ce qu'est une base de données serait de retour).
D'autres langues ont des installations de le faire: Python fournitures str.translate()
, dans Perl n'est tr/.../.../
, XPath est une fonction translate()
, ColdFusion a ReplaceList()
. Mais qu'en JavaScript?
Voici ce que j'ai droit maintenant.
//s would be a rather short string (something like
//200 characters at max, most of the time much less)
function makeSortString(s) {
var translate = {
"ä": "a", "ö": "o", "ü": "u",
"Ä": "A", "Ö": "O", "Ü": "U" //probably more to come
};
var translate_re = /[öäüÖÄÜ]/g;
return ( s.replace(translate_re, function(match) {
return translate[match];
}) );
}
Pour commencer, je n'aime pas le fait que la regex est reconstruit à chaque fois que j'appel de la fonction. Je suppose que la fermeture peut aider à cet égard, mais je ne semble pas obtenir le blocage de celui-ci pour une raison quelconque.
Quelqu'un peut-il penser à quelque chose de plus efficace?
Réponses ci-dessous se divisent en deux catégories:
- Chaîne de fonctions de remplacement de divers degrés de l'intégrité et de l'efficacité (ce que j'ai été à l'origine de demander à propos de)
- Un la fin de mentionner de
String#localeCompare
, qui est largement soutenu parmi les moteurs JS et pourrait résoudre cette catégorie de problème beaucoup plus élégamment.
- Vous êtes mal dans votre hypothèse que l'utilisateur s'attend à "ä" pour être trié, "un". Le suédois alphabet a 29 lettres: abcdefghijklmnopqrstuvwxyzåäö et le danois/norvégien: abcdefghijklmnopqrstuvwxyzæøå. L'ordre attendu est: "Apelsin", "Banane", "Äpple".
- Je sais. La solution a été prévu pour trier texte allemand. Même là, il n'est pas correct, mais assez bon pour le cas d'utilisation. Cette question n'a jamais été destiné à être la recherche de la "résout tous les problèmes" de l'algorithme.
- J'ai reformulé la question un peu pour que cela soit clair dès le début.
- J'ai trouvé votre question lorsque j'étais en suivant un lien depuis une autre question à propos de "u" et "ü" et avait pour objet. Mais maintenant que vous avez précisé que c'était pour l'allemand, je n'ai rien à objecter.
- Je préfère une courte discussion dans les commentaires sur un vote à tout moment. Malheureusement il y a des gens ici que le vote d'abord et poser des questions plus tard (le cas échéant). Conséquence: Votre commentaire a été appréciée. 🙂
- il y a des gens qui downvote pour aucune raison apparente,même les réponses correctes et les eaux limpides de questions... je me demande si l'remarqué qu'ils ne se perd 1 point?Je préfère laisser un commentaire au lieu donc l'auteur peut apporter des précisions/corrections. À mon humble avis c'est mieux.
- Juste pour que vous le savez, j'ai une fourchette de tablesorter dans lequel j'ai modifié les original
sortLocaleCompare
option pour remplacer ces accentué les chaînes automatiquement; veuillez consulter la cette démo pour plus de détails. Si cela ne fonctionne pas pour vous, alors découvrez cette démo qui remplace le texte par défaut en mode trieuse avec sugar.js. - Merci @Mottie. (Je crois
sortLocaleCompare
n'existaient même pas quand j'ai écrit pour la première fois à cette question.) - En fait, il n'existe pas dans la v2.0.5 (sans-papiers) et tout ce qu'il a fait a été
return a.localeCompare(b);
dans une sorte. - voir plus récente solution de stackoverflow.com/a/18391901/759452
- Il est MNP package qui fait juste cela, github.com/andrewrk/node-diacritics.
Vous devez vous connecter pour publier un commentaire.
Je ne peux pas parler de ce que vous essayez de faire précisément avec la fonction elle-même, mais si vous n'aimez pas les regex se construit à chaque fois, voici deux solutions et quelques mises en garde à propos de chacun d'eux.
Ici est une façon de le faire:
Cela va évidemment faire la regex une propriété de la fonction elle-même. La seule chose que vous n'aimez pas à propos de cette (ou vous pouvez, je suppose que cela dépend), c'est que la regex peut maintenant être modifiée à l'extérieur de la fonction du corps. Donc, quelqu'un pourrait le faire pour modifier le interally-utilisé les regex:
Donc, il ya cette option.
Une façon d'obtenir une fermeture, et donc d'empêcher quelqu'un d'en modifier la regex, serait à la définir comme une fonction anonyme affectation comme ceci:
J'espère que cela est utile pour vous.
Mise à JOUR: C'est le début et je ne sais pas pourquoi je n'ai pas vu l'évidence avant, mais il pourrait également être utile de vous mettre
translate
objet d'une fermeture ainsi:var translate_re = /[éáűőúöüóíÉÁŰPŐÚÖÜÓÍ]/g; var translate = { "é": "e", "á": "a", "ű": "u", "ő": "o", "ú": "u", "ö": "o", "ü": "u", "ó": "o", "í": "i", "É": "E", "Á": "A", "Ű": "U", "Ő": "O", "Ú": "U", "Ö": "O", "Ü": "U", "Ó": "O", "Í": "I" };
var translate_re = /[șțăîâȘȚĂÎÂ]/g; var translate = { "ș": "s", "ț": "t", "ă": "a", "î": "i", "â": "a", "Ș": "S", "Ț": "T", "Ă": "A", "Î": "I", "Â": "A" };
La terminologie correcte pour de tels accents est signes Diacritiques. Après Googler ce terme, j'ai trouvé cette fonction qui fait partie de
backbone.paginator
. Il a une collection très complète de signes Diacritiques et les remplace par leur plus intuitive de caractères ascii. J'ai trouvé ceci pour être le plus complet Javascript solution disponible aujourd'hui.La fonction complète pour référence future:
Basé sur la solution par Jason Bunting, voici ce que j'utilise maintenant.
Toute la chose est pour le jQuery tablesorter plug-in: Pour (presque correct) tri des non-anglais tables avec plugin tablesorter il est nécessaire de faire usage d'une coutume
textExtraction
function.Celui-ci:
'dd.mm.yyyy'
) à un format reconnu ('yyyy-mm-dd'
)Être prudent pour enregistrer le fichier JavaScript dans le codage UTF-8 ou il ne fonctionnera pas.
Vous pouvez l'utiliser comme ceci:
Í
ou leÍ
. Il ne fait aucune différence, tant que les paramètres d'encodage sont corrects (PHP, le codage de fichier, serveur PHP perçue encodage de fichier, HTTP Content-Type d'en-tête, les balises meta HTML). À l'aide de l'entité HTML peut-être plus sécuritaire. Si l' .js fichier est codé en UTF-8, il doit être servi en tant que telle (text/javascript; Charset=UTF-8
), alors tout doit être bien.sitemap-up.gif
etsitemap-down.gif
, je reçois 401 Accès Refusé pour eux.Content-Type: text/html
sansCharset
paramètre. Ils devraient au moins êtreContent-Type: text/javascript;
. Aussi, votreGetTextExtractor()
méthode (l'un enjquery.tablesorter.min.js
) diffère assez fortement de ma fonction, aucune idée de pourquoi vous pensez que vous pourriez travailler. 😉 Astuce: Mettre le texte de l'extracteur dansscripts.js
, non pas dans le plugin tablesorter code. Vous ne devriez pas toucher le code du plugin pour éviter à l'avenir des maux de tête.$("table.sortable").tablesorter(…);
, mais votre table est en fait$("table.tablesorter")
. Aussi, il n'est pas nécessaire d'appelertablesorter()
un deuxième temps. Une fois que vous effectuer le changement, c'est d'aller travailler - je viens de tester via FireBug.Je pense que ce serait un peu de nettoyant/mieux (mais je n'ai pas de test de performance):
Ou si vous êtes encore trop inquiet au sujet de la performance, nous allons obtenir le meilleur des deux mondes:
MODIFIER (par @Tomalak)
J'apprécie l'idée. Cependant, il y a plusieurs choses qui clochent dans la mise en œuvre, comme indiqué dans le commentaire ci-dessous.
Ici est de savoir comment je voudrais mettre en œuvre.
String.indexOf()
.eval()
. Il estnew RegExp()
pour que. Deuxièmement, il modifie la Chaîne de prototype. La modification des types de données intégrés est très mal vu. Troisièmement, la fonction s'exécute pour chaque caractère de la boucle à chaque invocation. C'est ce que j'ai essayé d'éviter en premier lieu. Cela signifie qu'il résout la lisibilité au détriment de la performance, que je considère comme un mauvais compromis. J'apprécie l'idée, mais l'exécution est sous-optimale. 🙂var stripAccents = function(s){ var in_chrs = ... }
? jsfiddlestripAccents()
est appelé. Voir les fermetures.Simplement doit être normalisé et de la chaîne d'exécuter un codes de remplacement:
Voir normaliser
Alors vous pouvez utiliser cette fonction:
https://stackoverflow.com/a/37511463
Intl.Collator(undefined , {sensitivity: 'base'})
La solution complète à votre demande:
Si vous êtes à la recherche spécifiquement pour un moyen de convertir les caractères accentués pour les non-caractères accentués, plutôt qu'une façon de trier les caractères accentués, avec un peu de finagling, la Chaîne.localeCompare fonction peut être manipulé pour trouver le latin de base de caractères qui correspondent à la élargies. Par exemple, vous pouvez produire un homme sympathique url slug à partir d'une page de titre. Si oui, vous pouvez faire quelque chose comme ceci:
JS:
Cela devrait effectuer très bien, mais si la poursuite de l'optimisation, une recherche binaire peut être utilisé avec
localeCompare
comme le comparateur de localiser le caractère de base. Notez que le cas est préservée, et des options permettent la préservation, le remplacement ou la suppression des caractères qui ne sont pas alphabétique, ou n'ont pas de correspondance des caractères latins, ils peuvent être remplacés par des. Cette mise en œuvre est plus rapide et plus souple, et devrait travailler avec de nouveaux personnages comme ils sont ajoutés. L'inconvénient est que le composé de caractères comme 'ꝡ" doivent être traitées spécifiquement, s'ils ont besoin d'être pris en charge.J'ai fait une Version Prototype de ce:
À utiliser comme:
Cela va changer la Chaîne de a_o_u_A_O_U_ss
var newstr = teststring.strip();
etconsole.log()
que, ensuite, il travaille -- jsfiddle. Merci mec, c'est le plus concis et lisible de la méthode.En se basant sur les réponses existantes et des suggestions, j'ai créé ce:
Il utilise de vrais caractères au lieu de l'unicode liste et fonctionne bien.
Vous pouvez l'utiliser comme
Vous pouvez facilement convertir cette fonction pour ne pas être la chaîne de prototype. Cependant, comme je suis fan de l'utilisation de la chaîne de prototype dans de tels cas, vous devrez le faire vous-même.
Il y a longtemps je l'ai fait en Java et trouvé quelqu'un d'autre solution basée sur une chaîne unique qui capte une partie de l'Unicode table qui a été important pour la conversion - le reste a été converti ? ou tout autre caractère de remplacement. J'ai donc essayé de le convertir en JavaScript. L'esprit que je ne suis pas un expert JS. 🙂
Ce convertit la plupart des latin1+2 caractères Unicode. Il n'est pas en mesure de traduire unique char à plusieurs. Je ne connais pas ses performances sur les JS, Java c'est de loin la manière la plus rapide de solutions communes (6-50x), il n'y a pas de carte, il n'y a pas de regex, rien. Il produit stricte sortie ASCII, potentiellement avec une perte d'information, mais la taille de la sortie correspond à l'entrée.
J'ai testé l'extrait de code avec http://www.webtoolkitonline.com/javascript-tester.html et il produit
Supa, co? lstczyaoa??
comme prévu.Pas une seule réponse mentionne
String.localeCompare
, qui arrive à faire exactement ce que vous vouliez à l'origine, mais pas ce que vous demandez.Le deuxième et le troisième paramètre ne sont pas pris en charge par les navigateurs plus anciens, cependant. C'est une option à considérer néanmoins.
Je voulais juste poster ma solution à l'aide String#localeCompare
JS:
Si vous souhaitez obtenir de tri où "ä" vient après "a" et n'est pas considéré comme le même, alors vous pouvez utiliser une fonction comme la mienne.
Vous pouvez toujours changer l'alphabet pour obtenir différents ou de même bizarre de tris. Toutefois, si vous souhaitez quelques lettres équivalentes, alors vous devez manipuler les chaînes de caractères comme
a = a.replace(/ä/, 'a')
ou similaire, comme beaucoup l'ont déjà répondu ci-dessus. J'ai inclus les lettres majuscules si quelqu'un veut avoir toutes les majuscules des mots avant de minuscules mots (alors vous devez omettre.toLowerCase()
).var
mot-clé. Cela signifie que chaque variable que vous déclarez est mondiale. Ce n'est certainement pas ce que vous aviez à l'esprit (il n'est pas automatique de la portée de la fonction en JS). Oubliervar
fait de méchants bugs. 2) Vous devez utiliser une fermeture au lieu de re-définition de l'alphabet à chaque appel de fonction. 3) Vous n'avez ni la vérification du type et ni stricte des comparaisons. - J'ai créé une version optimisée de votre fonction ici: jsperf.com/collation-string-sorting. À la fois sur Chrome et IE c'est près de 4 fois plus vite que votre approche.Une manière simple et facile:
Donc faire ceci:
De sortie:
Réponse os Crisalin est presque parfait. Seulement une amélioration de la performance afin d'éviter de créer de nouveaux RegExp à chaque exécution.
Utilisation:
Je ne peux pas penser à un moyen plus facile pour enlever efficacement les tous signes diacritiques, à partir d'une chaîne que l'utilisation de ce solution étonnante.
Le voir en action:
JS:
Espère que cela aide.
Je l'ai résolu d'une autre façon, si vous le souhaitez.
Ici, j'ai utilisé deux tableaux où searchChars contenant qui sera remplacé et replaceChars contenant des caractères désirés.
JS: