Python trie par valeur d'octet par défaut, 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?
Y a-t-il une bibliothèque pour cela? Je n'ai rien trouvé. De préférence, le tri doit prendre en charge la langue, de sorte qu'il comprend que åäö doit être trié après z en suédois, mais que ü doit être trié par u, etc.
S'il n'y a pas de bibliothèque pour cela, quelle est la meilleure façon de le faire? Faites simplement un mappage d'une lettre à une valeur entière et mappez la chaîne à une liste d'entiers avec ça?
locale.strcoll
réponse est correcte lorsque vous avez besoin d'un tri Unicode en utilisant les paramètres régionaux de l'utilisateur, et l'ICU répond à vos souhaits lorsque vous en avez besoin de plus (classement utilisant plusieurs paramètres régionaux). La plupart du temps, vous voulezlocale.strcoll
.locale.strcoll
fonctionne bien et surtout ce que ICU fait mieux que la fonction Python. Fondamentalement, un peu plus d'attention pour la question.--locale=de__phonebook
quand vous en avez besoin. Le module Perl réussit la suite de tests UCA, et le script que j'ai fourni rend beaucoup plus facile de jouer avec l'ensemble de l'UCA plus toutes ses options, y compris les paramètres régionaux, juste à partir de la ligne de commande. Peut-être ne pas répondre à la question, mais cela devrait tout de même être très intéressant. Si vous êtes en Suisse, je suis sûr que vous pouvez utiliser la flexibilité. :)Réponses:
La bibliothèque ICU d'IBM fait cela (et bien plus encore). Il a des liaisons Python: PyICU .
Mise à jour : La principale différence dans le tri entre ICU
locale.strcoll
est que ICU utilise l' algorithme de classement Unicode complet tout enstrcoll
utilisant ISO 14651 .Les différences entre ces deux algorithmes sont brièvement résumées ici: http://unicode.org/faq/collation.html#13 . Ce sont des cas particuliers plutôt exotiques, qui devraient rarement avoir une importance dans la pratique.
la source
locale.strxfrm
de la réponse par u0b34a0f6ae et il semble fonctionner et est beaucoup plus élégant et ne nécessite aucun logiciel supplémentaire.sudo pip3 install PyICU
ne parvient pas à s'installer, tout comme Python2.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.
Question à Lennart et aux autres répondants: Est-ce que personne ne connaît la «locale» ou n'est-ce pas à la hauteur de cette tâche?
la source
Essayez l' algorithme de classement Python Unicode de James Tauber . Il ne fait peut-être pas exactement ce que vous voulez, mais semble valoir le coup d'œil. Pour plus d'informations sur les problèmes, consultez cet article de Christopher Lenz.
la source
Vous pourriez également être intéressé par pyuca :
http://jtauber.com/blog/2006/01/27/python_unicode_collation_algorithm/
Bien que ce ne soit certainement pas le moyen le plus précis, c'est un moyen très simple de faire au moins un peu raison. Il bat également les paramètres régionaux dans une application Web, car les paramètres régionaux ne sont pas sûrs pour les threads et définissent les paramètres de langue à l'échelle du processus. Il est également plus facile à configurer que PyICU qui s'appuie sur une bibliothèque C externe.
J'ai téléchargé le script sur github car l'original était en panne au moment de la rédaction de cet article et j'ai dû recourir à des caches Web pour l'obtenir:
https://github.com/href/Python-Unicode-Collation-Algorithm
J'ai utilisé avec succès ce script pour trier correctement le texte allemand / français / italien dans un module plone.
la source
Une réponse synthétique et détaillée:
locale.strcoll
sous Python 2, etlocale.strxfrm
résoudra en fait le problème, et fait du bon travail, en supposant que vous avez installé la locale en question. Je l'ai également testé sous Windows, où les noms de 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 le fait pas nécessairement mieux dans la pratique, mais bien plus . Plus particulièrement, il prend en charge les séparateurs qui peuvent diviser des textes dans différentes langues en mots. Ceci est très utile pour les langues qui n'ont pas de séparateurs de mots. Vous aurez besoin d'un corpus de mots à utiliser comme base pour le fractionnement, car ce n'est pas inclus, cependant.Il a également des noms longs pour les paramètres régionaux afin que vous puissiez obtenir de jolis noms d'affichage pour les paramètres régionaux, la prise en charge d'autres calendriers que le grégorien (bien que je ne sois pas sûr que l'interface Python le prenne en charge) et des tonnes et des tonnes d'autres supports de paramètres régionaux plus ou moins obscurs .
Donc dans l'ensemble: si vous souhaitez trier par ordre alphabétique et en fonction des paramètres régionaux, vous pouvez utiliser le
locale
module, sauf si vous avez des exigences particulières, ou si vous avez également besoin de fonctionnalités plus dépendantes des paramètres régionaux, comme le séparateur de mots.la source
Je vois que les réponses ont déjà fait un excellent travail, je voulais juste souligner une inefficacité de codage dans Human Sort . Pour appliquer une traduction sélective char-par-char à une chaîne unicode s, il utilise le code:
Python a un moyen bien meilleur, plus rapide et plus concis 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! -):
Le dict que vous passez à la
translate
méthode a des ordinaux Unicode (et non des chaînes) comme clés, c'est pourquoi nous avons besoin de cette étape de reconstruction à partir du char-à-char d'originespec_dict
. (Les valeurs du dict que vous passez à 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 certains caractères à des fins de tri "," mapper ä à ae à des fins de tri ", etc.).Dans Python 3, vous pouvez obtenir l'étape de "reconstruction" plus simplement, par exemple:
Consultez la documentation pour découvrir d'autres façons d'utiliser cette
maketrans
méthode statique dans Python 3.la source
Pour l'implémenter, vous aurez besoin de lire sur "l'algorithme de classement Unicode" voir http://en.wikipedia.org/wiki/Unicode_collation_algorithm
http://www.unicode.org/unicode/reports/tr10/
un exemple d'implémentation est ici
http://jtauber.com/blog/2006/01/27/python_unicode_collation_algorithm/
la source
Dernièrement, j'utilise zope.ucol ( https://pypi.python.org/pypi/zope.ucol ) pour cette tâche. Par exemple, en triant l'allemand ß:
zope.ucol enveloppe également ICU, ce serait donc une alternative à PyICU.
la source
Une solution UCA complète
La manière la plus simple, la plus simple et la plus directe de le faire est de faire un appel au module de bibliothèque Perl, Unicode :: Collate :: Locale , qui est une sous-classe du module Unicode :: Collate standard . Tout ce que vous avez à faire est de transmettre au constructeur une valeur locale de
"xv"
pour la Suède.(Vous n'apprécierez peut-être pas nécessairement cela pour le texte suédois, mais comme Perl utilise des caractères abstraits, vous pouvez utiliser n'importe quel point de code Unicode que vous voulez - peu importe la plate-forme ou la construction! Peu de langues offrent une telle commodité. Je le mentionne parce que j'ai J'ai beaucoup perdu la bataille avec Java sur ce problème exaspérant ces derniers temps.)
Le problème est que je ne sais pas comment accéder à un module Perl à partir de Python - à part, c'est-à-dire en utilisant une légende de shell ou un tube à deux côtés. À cette fin, je vous ai donc fourni un script de travail complet appelé ucsort que vous pouvez appeler pour faire exactement ce que vous avez demandé avec une facilité parfaite.
Ce script est 100% compatible avec l' algorithme de classement Unicode complet , avec toutes les options de personnalisation prises en charge !! Et si un module optionnel est installé ou que vous exécutez Perl 5.13 ou supérieur, vous avez un accès complet aux locales CLDR faciles à utiliser. Voir ci-dessous.
Manifestation
Imaginez un ensemble d'entrée ordonné de cette façon:
Un tri par défaut par point de code donne:
ce qui est incorrect dans le livre de tout le monde. En utilisant mon script, qui utilise l'algorithme de classement Unicode, vous obtenez cet ordre:
C'est le tri UCA par défaut. Pour obtenir les paramètres régionaux suédois, appelez ucsort de cette façon:
Voici une meilleure démo d'entrée. Tout d'abord, l'ensemble d'entrée:
Par point de code, cela trie de cette façon:
Mais l'utilisation de l'UCA par défaut permet de le trier de cette façon:
Mais dans la langue suédoise, de cette façon:
Si vous préférez trier les majuscules avant les minuscules, procédez comme suit:
Sortes personnalisées
Vous pouvez faire beaucoup d'autres choses avec ucsort . Par exemple, voici comment trier les titres en anglais:
Vous aurez besoin de Perl 5.10.1 ou supérieur pour exécuter le script en général. Pour la prise en charge des paramètres régionaux, vous devez soit installer le module CPAN en option
Unicode::Collate::Locale
. Vous pouvez également installer une version de développement de Perl, 5.13+, qui inclut ce module en standard.Conventions d'appel
Il s'agit d'un prototype rapide, donc ucsort n'est généralement pas (der) documenté. Mais voici son SYNOPSIS des commutateurs / options qu'il accepte sur la ligne de commande:
Ouais, ok: c'est vraiment la liste d'arguments que j'utilise pour l'appel
Getopt::Long
, mais vous voyez l'idée. :)Si vous pouvez trouver comment appeler directement des modules de bibliothèque Perl depuis Python sans appeler un script Perl, faites-le par tous les moyens. Je ne sais pas comment faire moi-même. J'adorerais apprendre comment.
En attendant, je pense que ce script fera tout ce dont vous avez besoin dans ses particularités - et plus encore! J'utilise maintenant ceci pour tout le tri de texte. Il fait enfin ce dont j'avais besoin depuis très, très longtemps.
Le seul inconvénient est que cet
--locale
argument entraîne une baisse des performances dans les tubes, bien que cela soit suffisamment rapide pour un tri régulier, non local mais toujours 100% conforme à UCA . Puisqu'il charge tout en mémoire, vous ne voudrez probablement pas l'utiliser sur des documents gigaoctets. Je l'utilise plusieurs fois par jour, et c'est vraiment génial d'avoir enfin un tri de texte sain.la source
Il est loin d' être une solution complète pour votre cas d'utilisation, mais vous pouvez jeter un oeil à l' unaccent.py script à partir effbot.org. Ce qu'il fait essentiellement, c'est supprimer tous les accents d'un texte. Vous pouvez utiliser ce texte «épuré» pour trier par ordre alphabétique. (Pour une meilleure description, consultez cette page.)
la source
Jeff Atwood a écrit un bon article sur l'ordre de tri naturel , dans lequel il a lié à un script qui fait peu près ce que vous demandez .
Ce n'est en aucun cas un script trivial, mais il fait l'affaire.
la source