Trier des chaînes alphanumériques en python

publié le 15 March 2011

[en] A nice and quick solution for sorting alphanumeric strings in "natural order" (e.g. sorting "Max. speed 5 Km/h" before "Max speed 10 Km/h") in Python.

En concevant une page de Swiss-timber-bridges, j'ai été confronté à un problème classique: trier des chaînes alphanumériques en python, dans un ordre alphabétique mais qui respecte l'ordre naturel des nombres.

En gros, l'idée était de classer des chaînes du genre

  • "Vitesse maximale 5 Km/h"
  • "Vitesse maximale 10 Km/h"
  • ...

dans leur ordre "naturel". Évidemment, modifier le libellé en "Vitesse maximale 05 Km/h" n'était pas une solution envisageable.

En m'inspirant d'une réponse sur stack overflow, je me suis rendu compte que cela pouvait se faire très simplement. En gros, l'idée est la suivante:

  • On commence par "splitter" la chaîne de caractères pour isoler tous les nombres. Donc notre "Vitesse maximale 5 Km/h" devient ["Vitesse maximale ", "5", " Km/h"].
  • On convertit ensuite les chaînes représentant des nombres en nombres: ["Vitesse maximale ", 5, " Km/h"].
  • Enfin, on utilise cette liste comme clé de tri.

C'est bien entendu plus long à expliquer qu'à coder:

convert = lambda text: int(text) if text.isdigit() else text 
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
objects.sort(key=lambda x: alphanum_key(x.code))

Bien entendu, cette solution n'est pas d'une efficacité irréprochable. Mais pour des petites quantités de données à trier... disons que ce n'est pas mauvais pour 3 lignes de code!