112 votes

Comment trier les chaînes unicode par ordre alphabétique en Python ?

Par défaut, Python trie par valeur d'octet, ce qui signifie que é vient après z et d'autres choses tout aussi amusantes. Quelle est la meilleure façon de trier par ordre alphabétique en Python ?

Existe-t-il une bibliothèque pour cela ? Je n'ai rien trouvé. De préférence, le tri devrait avoir un support linguistique afin de comprendre que åäö devrait être trié après z en suédois, mais que ü devrait être trié par u, etc. La prise en charge d'Unicode est donc pratiquement une obligation.

S'il n'existe pas de bibliothèque pour cela, quelle est la meilleure façon de le faire ? Il suffit de faire un mappage de la lettre à une valeur entière et de mapper la chaîne à une liste d'entiers avec cela ?

12 votes

Notez que cela dépend encore plus de la localité : En suédois (comme vous le dites), "Ä" vient après "Z", mais en allemand, "Ä" est généralement trié comme "AE".

0 votes

@Georg : Y a-t-il une raison pour laquelle vous avez ouvert une prime sur ce sujet ? Le site locale.strcoll La réponse est correcte lorsque vous avez besoin d'un tri Unicode utilisant la locale de l'utilisateur, et l'ICU répond à ce que vous voulez lorsque vous avez besoin de plus que cela (collation utilisant plus d'une locale). La plupart du temps, vous voulez locale.strcoll .

0 votes

@Glenn : Je voulais savoir à quel point locale.strcoll et surtout ce que UNITÉ DE SOINS INTENSIFS fait mieux que la fonction Python. En gros, un peu plus d'attention pour la question.

83voto

Rafał Dowgird Points 16600

IBM UNITÉ DE SOINS INTENSIFS fait cela (et bien plus encore). Elle a des liens avec Python : PyICU .

Mise à jour : La principale différence de tri entre l'USI et locale.strcoll est que l'ICU utilise la totalité Algorithme de collationnement d'Unicode tandis que strcoll utilise ISO 14651 .

Les différences entre ces deux algorithmes sont brièvement résumées ici : http://unicode.org/faq/collation.html#13 . Il s'agit de cas particuliers plutôt exotiques, qui devraient rarement avoir de l'importance dans la pratique.

>>> import icu # pip install PyICU
>>> sorted(['a','b','c','ä'])
['a', 'b', 'c', 'ä']
>>> collator = icu.Collator.createInstance(icu.Locale('de_DE.UTF-8'))
>>> sorted(['a','b','c','ä'], key=collator.getSortKey)
['a', 'ä', 'b', 'c']

0 votes

Cela fonctionne-t-il de la même manière pour Python 2 et Python 3 ? J'ai utilisé locale.strxfrm à partir de la réponse de u0b34a0f6ae et cela semble fonctionner et est beaucoup plus élégant et ne nécessite aucun logiciel supplémentaire.

1 votes

Ne fonctionne pas avec Python3 pour moi, sudo pip3 install PyICU ne s'installe pas et il en est de même pour Python2.

0 votes

J'ai dû installer libicu-devel.x86_64 pour que pyICU puisse compiler et installer à partir de Pip. Cela fonctionne, bien que la sortie de la dernière commande 'sorted' soit : ['a', ' \xc3\xa4 ', 'b', 'c']

59voto

u0b34a0f6ae Points 14874

Je ne vois pas cela dans les réponses. Mon application trie en fonction de la locale en utilisant la bibliothèque standard de Python. C'est assez simple.

# python2.5 code below
# corpus is our unicode() strings collection as a list
corpus = [u"Art", u"Älg", u"Ved", u"Wasa"]

import locale
# this reads the environment and inits the right locale
locale.setlocale(locale.LC_ALL, "")
# alternatively, (but it's bad to hardcode)
# locale.setlocale(locale.LC_ALL, "sv_SE.UTF-8")

corpus.sort(cmp=locale.strcoll)

# in python2.x, locale.strxfrm is broken and does not work for unicode strings
# in python3.x however:
# corpus.sort(key=locale.strxfrm)

Question à Lennart et aux autres personnes qui ont répondu : Quelqu'un connaît-il 'locale' ou n'est-il pas à la hauteur de cette tâche ?

0 votes

Au fait 1) Je ne pense pas que locale.strxfrm soit cassé pour les `str' encodés en UTF-8 ; j'ai fait un benchmarking par application et j'ai conclu que l'utilisation de cmp=strcoll sur les objets unicode est moins chère que le décodage en UTF-8 et l'utilisation de key=strxfrm.

6 votes

A propos 2) Le module locale ne fonctionnera qu'avec les locales générées (pour une machine Linux), pas avec n'importe quelle locale arbitraire. "locale -a" vous dira quelle

0 votes

Quelqu'un peut-il confirmer si cela fonctionne ? Si oui, pourquoi y a-t-il tant de réponses utilisant des bibliothèques externes ?

10voto

Vinay Sajip Points 41286

Essayez le livre de James Tauber Algorithme de collation Unicode en Python . Il se peut qu'il ne fasse pas exactement ce que vous voulez, mais il vaut la peine d'y jeter un coup d'œil. Pour un peu plus d'informations sur ces questions, voir ce poste par Christopher Lenz.

0 votes

Cela résout au moins le problème générique. Je suppose que des versions sensibles à la langue de la liste de collation pourraient également être créées.

0 votes

Cela ne vous permet pas de spécifier la locale, et le fichier de configuration de référence provoque une ValueError.

8voto

Lennart Regebro Points 52510

Un résumé et une réponse étendue :

locale.strcoll sous Python 2, et locale.strxfrm résoudra en fait le problème, et fait un bon travail, en supposant que la locale en question soit installée. Je l'ai également testé sous Windows, où les noms des paramètres régionaux sont différents, mais d'un autre côté, il semble que tous les paramètres régionaux pris en charge soient installés par défaut.

ICU ne fait pas nécessairement mieux dans la pratique, mais il permet cependant de plus . Il prend notamment en charge les séparateurs qui permettent de diviser en mots des textes dans différentes langues. Ceci est très utile pour les langues qui n'ont pas de séparateurs de mots. Vous devrez disposer d'un corpus de mots à utiliser comme base pour le découpage, car cela n'est pas inclus, cependant.

Il possède également des noms longs pour les locales afin que vous puissiez obtenir de jolis noms d'affichage pour la locale, le support pour d'autres calendriers que le grégorien (bien que je ne sois pas sûr que l'interface Python le supporte) et des tonnes et des tonnes d'autres supports de locale plus ou moins obscurs.

Donc, dans l'ensemble : Si vous souhaitez effectuer un tri alphabétique et dépendant de la localisation, vous pouvez utiliser la fonction locale à moins que vous n'ayez des exigences particulières, ou que vous ayez besoin de fonctionnalités plus dépendantes de la langue, comme le séparateur de mots.

6voto

Alex Martelli Points 330805

Je vois que les réponses ont déjà fait un excellent travail, je voulais juste souligner une inefficacité de codage dans Triage humain . Pour appliquer une traduction sélective caractère par caractère à une chaîne unicode s, il utilise le code :

spec_dict = {'Å':'A', 'Ä':'A'}

def spec_order(s):
    return ''.join([spec_dict.get(ch, ch) for ch in s])

Python dispose d'une méthode bien meilleure, plus rapide et plus concise pour effectuer cette tâche auxiliaire (sur les chaînes Unicode -- la méthode analogue pour les chaînes d'octets a une spécification différente et un peu moins utile!-) :

spec_dict = dict((ord(k), spec_dict[k]) for k in spec_dict)

def spec_order(s):
    return s.translate(spec_dict)

Le dict que vous passez au translate a des ordinaux Unicode (et non des chaînes de caractères) comme clés, c'est pourquoi nous avons besoin de cette étape de reconstruction de la méthode originale char-to-char spec_dict . (Les valeurs dans le dict que vous passez pour traduire [par opposition aux clés, qui doivent être des ordinaux] peuvent être des ordinaux Unicode, des chaînes Unicode arbitraires, ou None pour supprimer le caractère correspondant dans le cadre de la traduction, il est donc facile de spécifier "ignorer un certain caractère à des fins de tri", "faire correspondre ä à ae à des fins de tri", et ainsi de suite).

En Python 3, vous pouvez obtenir l'étape de "reconstruction" plus simplement, par ex :

spec_dict = ''.maketrans(spec_dict)

Ver les docs pour d'autres façons d'utiliser cet outil maketrans méthode statique en Python 3.

0 votes

Cette méthode est intéressante mais ne permet pas de placer á entre az et b.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X