Python ont une fonction intégrée de la chaîne naturelle de tri?
À L'Aide De Python 3.x, j'ai une liste de chaînes de caractères, et j'aimerais effectuer un naturel tri alphabétique.
Naturel de tri: L'ordre dans lequel les fichiers dans Windows sont triés.
Par exemple, la liste suivante est naturellement triés (ce que je veux):
['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13']
Et voici la "triés" version de la liste ci-dessus (ce que j'ai):
['Elm11', 'Elm12', 'Elm2', 'elm0', 'elm1', 'elm10', 'elm13', 'elm9']
Je suis à la recherche d'une fonction de tri qui se comporte comme le premier.
- La définition d'un naturel tri n'est pas "l'ordre de Windows sortes de fichiers".
- connexes: Python analogique de natsort fonction (tri d'une liste à l'aide d'un "ordre naturel" de l'algorithme)
Vous devez vous connecter pour publier un commentaire.
Il y a un tiers de la bibliothèque pour cette sur PyPI appelé natsort (divulgation complète, je suis le package de l'auteur). Pour votre cas, vous pouvez effectuer une des opérations suivantes:
Vous devriez noter que
natsort
utilise un algorithme général, donc ça devrait marcher juste au sujet de toutes les suggestions que vous jeter à elle. Si vous souhaitez plus de détails sur pourquoi vous pouvez choisir une bibliothèque pour ce faire, plutôt que de rouler votre propre fonction, consultez lanatsort
de la documentation de Comment Ça Marche page, en particulier la Cas Particuliers Partout! section.Si vous avez besoin d'une clé de tri au lieu d'une fonction de tri, utilisez l'une des ci-dessous les formules.
Essayez ceci:
De sortie:
Voir en ligne: ideone.
Code adapté à partir d'ici: De tri pour les êtres Humains : Naturel, l'Ordre de Tri.
return sorted(l, key)
au lieu del.sort(key)
? Est-ce pour tout gain de performances ou tout simplement pour être plus pythonic?re.split('([0-9]+)', '0foo')
retourne['', '0', 'foo']
. À cause de cela, les chaînes seront toujours sur le même index et les entiers impairs index dans le tableau.Voici un beaucoup plus pythonic version de Marque Byer réponse:
Maintenant cette fonction peut être utilisé comme une clé dans une fonction qui l'utilise, comme
list.sort
,sorted
,max
, etc.Comme un lambda:
J'ai écrit une fonction sur la base http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html qui ajoute la possibilité de toujours passer dans votre propre paramètre 'key'. J'ai besoin de ce dans le but d'effectuer un naturel de tri de listes qui contiennent des objets plus complexes (et pas seulement des chaînes de caractères).
Par exemple:
natural_sort_key
, puis lors du tri d'une liste que vous pourriez faire de la chaîne de vos clés, par exemple:list.sort(key=lambda el: natural_sort_key(el['name']))
Nous allons analyser les données. Les chiffres de la capacité de tous les éléments est de 2. Et il y a 3 lettres en commun littérale partie
'elm'
.Donc, la longueur maximale de l'élément est de 5. On peut augmenter cette valeur pour s'assurer (par exemple, à 8).
Gardant cela à l'esprit, nous avons une solution en ligne:
sans expressions régulières et des bibliothèques externes!
Explication:
width = max(data, key=len)
de calculer des sous pour la8
ci-dessus et ensuite les sous dans la chaîne de format avec'{0:0>{width}}'.format(x, width=width)
Donné:
Similaire à Serge de solution, un 1-liner sans bibliothèques externes serait:
ou
Explication:
Cette solution utilise le clé fonction de sorte de définir une fonction qui va être utilisé pour le tri. Parce que nous savons que chaque entrée est précédée par "l'orme" la fonction de tri convertit en entier la partie de la chaîne après la 3e personnage (c'est à dire de type int(x[3:])). Si la partie numérique de données est dans un emplacement différent, cette partie de la fonction serait de changer.
Acclamations
Et maintenant pour quelque chose de plus* élégant (pythonic) -juste une touche
Il existe de nombreuses implémentations, et alors que certains sont proches, aucun bien capturé l'élégance moderne python offre.
les numéros sont en milieu de chaîne
Rapidement
Plein De Code
Attention lors de l'utilisation de
from os.path import split
Inspiration de
Une option est de transformer la chaîne de caractères dans un n-uplet et remplacer des caractères à l'aide forme développée http://wiki.answers.com/Q/What_does_expanded_form_mean
de cette façon a90 deviendrait ("un",90,0) et a1 deviendrait ("a",1)
ci-dessous est un exemple de code (qui n'est pas très efficace en raison de la façon dont Elle supprime 0 de nombres)
de sortie:
('b', 1) < ('b', 'e', 't', 'a', 1, '.', 1)
sera de retourTypeError: unorderable types: int() < str()
Sur la base des réponses ici, j'ai écrit un
natural_sorted
fonction qui se comporte comme la fonction intégréesorted
:Le code source est également disponible sur mon GitHub extraits du référentiel:
https://github.com/bdrung/snippets/blob/master/natural_sorted.py
Valeur De Ce Post
Mon point est d'offrir à un non regex solution qui peut s'appliquer de manière générale.
Je vais créer trois fonctions:
find_first_digit
qui j'ai emprunté de @AnuragUniyal. Il va trouver la position du premier chiffre ou non de chiffres dans une chaîne de caractères.split_digits
qui est un générateur qui prend en outre une chaîne en chiffres et non des chiffres morceaux. Il sera égalementyield
des entiers quand c'est un chiffre.natural_key
juste enveloppementssplit_digits
dans untuple
. C'est ce que nous utilisons comme une clé poursorted
,max
,min
.Fonctions
On peut voir que c'est général que nous pouvons avoir plusieurs chiffres morceaux:
Ou laisser comme sensible à la casse:
Nous pouvons voir qu'il trie les OP de la liste, dans l'ordre
Mais il peut gérer plus compliqué listes ainsi:
Ma regex équivalent serait
Les réponses ci-dessus sont bonnes pour la exemple précis qui a été montré, mais manquer plusieurs cas utiles pour la question plus générale de naturel de tri. Je viens de peu par l'un de ces cas, afin de créer une meilleure solution complète:
Le code de Test et plusieurs liens (sur et en dehors de StackOverflow) sont ici:
http://productarchitect.com/code/better-natural-sort.py
Commentaires de bienvenue. Ce n'est pas destiné à être une solution définitive; juste un pas en avant.
natsorted
ethumansorted
échouent parce qu'ils ont été utilisés de manière incorrecte... vous avez essayé de passernatsorted
comme une clé mais sa en fait la fonction de tri lui-même. Vous devriez avoir essayénatsort_keygen()
.Plus susceptibles
functools.cmp_to_key()
est étroitement liée à l'implémentation sous-jacente de python de la sorte. En outre, la cmp paramètre est l'héritage. La façon moderne est de transformer des éléments d'entrée en objets qui prennent en charge l'souhaité riche d'opérations de comparaison.En Vertu De Disponible 2.x, des objets de différents types peuvent être ordonnée même si le riche opérateurs de comparaison n'ont pas été mises en œuvre. En Vertu De Disponible 3.x, des objets de types différents devez explicitement de soutenir la comparaison. Voir Comment Python comparer string et int? qui relie le la documentation officielle. La plupart des réponses dépendent de l'implicite de la commande. De commutation pour Python 3.x nécessitera un nouveau type de mettre en œuvre et d'unifier les comparaisons entre les nombres et les chaînes de caractères.
Il existe trois approches différentes. Le premier utilise des classes imbriquées à prendre avantage de Python
Iterable
de l'algorithme de comparaison. La deuxième se déroule cette imbrication dans une seule classe. La troisième renonce à sous-classementstr
de se concentrer sur la performance. Tous sont chronométrés; la seconde est deux fois plus rapide tandis que le troisième près de six fois plus. Sous-classementstr
n'est pas nécessaire, et était probablement une mauvaise idée en premier lieu, mais il ne viennent avec certaines convenances.Le genre de personnages sont dupliqués à la force de la commande par cas, et le cas échangés à la force d'une lettre minuscule pour trier d'abord; c'est le cas typique de la définition de "naturel de tri". Je ne pouvais pas décider sur le type de groupement; certains préféreront peut-être la suivante, ce qui apporte également d'importants avantages de performance:
S'il y a lieu, les opérateurs de comparaison sont à
object
donc ils ne seront pas être ignoré parfunctools.total_ordering
.Tri naturel est à la fois très compliqué et vaguement défini comme un problème. N'oubliez pas d'exécuter
unicodedata.normalize(...)
à l'avance, et envisager d'utiliserstr.casefold()
plutôt questr.lower()
. Il y a probablement subtile problèmes d'encodage, je n'ai pas considéré. J'ai donc provisoirement recommander la natsort de la bibliothèque. J'ai pris un coup d'oeil rapide sur le dépôt github; le code de la maintenance a été stellaire.Tous les algorithmes que j'ai vu dépendent des astuces telles que la duplication et l'abaissement des caractères, et d'échanger sur les cas. Tout cela double le temps d'exécution, une autre solution nécessiterait un total de l'ordre naturel à l'entrée du jeu de caractères. Je ne pense pas que ce est une partie de la spécification unicode, et depuis il y a beaucoup plus d'unicode chiffres que
[0-9]
, la création d'un tel tri serait tout aussi redoutable. Si vous voulez locale-connaissance des comparaisons, préparez vos cordes avecparamètres régionaux.strxfrm
par Python Tri COMMENT.Je vous suggère de simplement utiliser le
key
argument mot-clé desorted
à atteindre vos listePar exemple:
Remerciements:
Tri À Bulles Devoirs
Comment lire une chaîne de caractères une lettre à la fois en python
re
partie?