Skip to content

Trier une liste de chaînes numériques en Python

En Python, vous pouvez trier une liste avec la méthode sort() ou la fonction sorted().

Cet article décrit comment trier une liste de chaînes numériques non remplies de zéros.

  • trier() et trier()
  • Remarques sur les chaînes numériques non remplies de zéros
  • Spécifiez int() ou float() pour le paramètre clé
  • Extraire des nombres dans des chaînes avec des expressions régulières
    • Un seul nombre dans une chaîne
    • Plus d’un nombre dans une chaîne
    • Certains éléments n’ont pas de numéro dans une chaîne

trier() et trier()

sort() est une méthode d’une liste, qui trie la liste d’origine elle-même.

l = [10, 1, 5]

l.sort()
print(l)
# [1, 5, 10]

trié() est une fonction intégrée qui crée une nouvelle liste triée. La liste d’origine n’est pas modifiée.

l = [10, 1, 5]

print(sorted(l))
# [1, 5, 10]

print(l)
# [10, 1, 5]

Par défaut, le tri s’effectue par ordre croissant. Si vous souhaitez trier par ordre décroissant, définissez le paramètre reverse sur True. L’exemple utilise sorted(), mais vous pouvez également utiliser sort().

print(sorted(l, reverse=True))
# [10, 5, 1]

Pour plus d’informations, notamment sur le tri des tuples et des chaînes, consultez l’article suivant.

Remarques sur les chaînes numériques non remplies de zéros

Dans le cas d’une liste de chaînes numériques remplies de zéros, elle est triée sans problème. Notez que l’exemple de code suivant utilise sorted(), mais il en va de même pour sort().

l = ['10', '01', '05']

print(sorted(l))
# ['01', '05', '10']

Dans le cas d’une liste de chaînes numériques non remplies de zéros, les chaînes sont triées dans l’ordre du dictionnaire et non sous forme de nombres. Par exemple, ’10’ est considéré comme inférieur à ‘5’.

l = ['10', '1', '5']

print(sorted(l))
# ['1', '10', '5']

Spécifiez int() ou float() pour le paramètre clé

sort() et sorted() ont le paramètre key.

En spécifiant int() ou float(), qui convertit une chaîne en nombre, pour le paramètre clé, une liste de chaînes numériques est triée en nombres, et non en chaînes.

Lorsqu’une fonction est spécifiée comme argument, () n’est pas nécessaire.

l = ['10', '1', '5']

print(sorted(l, key=int))
# ['1', '5', '10']

print(sorted(l, key=float))
# ['1', '5', '10']

Les chaînes entières peuvent être converties avec int() ou float(), mais les décimales doivent être converties avec float().

l = ['10.0', '1.0', '5.0']

print(sorted(l, key=float))
# ['1.0', '5.0', '10.0']

Le sort() a également le paramètre clé.

l = ['10', '1', '5']

l.sort(key=int)
print(l)
# ['1', '5', '10']

Comme vous pouvez le voir à partir des résultats jusqu’à présent, la fonction spécifiée pour la clé n’est appliquée qu’à des fins de comparaison et le résultat reste l’original.

Si vous voulez que le résultat soit int ou float, triez simplement la liste convertie à l’aide des compréhensions de liste.

l = ['10', '1', '5']

print([int(s) for s in l])
# [10, 1, 5]

print(sorted([int(s) for s in l]))
# [1, 5, 10]

Pour les chaînes numériques, vous n’avez qu’à spécifier int() ou float() pour key.

Cependant, pour les chaînes contenant des nombres intégrés, vous devez utiliser le module d’expression régulière re pour extraire la partie numérique de la chaîne.

l = ['file10.txt', 'file1.txt', 'file5.txt']

Un seul nombre dans une chaîne

Obtenez un objet match par search() et prenez la partie correspondante comme une chaîne avec la méthode group().

Utilisez d+ comme modèle d’expression régulière. d est un nombre, + est une répétition d’un ou plusieurs caractères et d+ correspond à une séquence d’un ou plusieurs nombres.

import re

s = 'file5.txt'

print(re.search(r'd+', s).group())
# 5

Cet exemple de code utilise une chaîne brute.

Puisqu’une chaîne est renvoyée, utilisez int() ou float() pour la convertir en nombre.

print(type(re.search(r'd+', s).group()))
# <class 'str'>

print(type(int(re.search(r'd+', s).group())))
# <class 'int'>

Avec une expression lambda, vous pouvez spécifier ce processus pour le paramètre clé de sort() ou sorted().

l = ['file10.txt', 'file1.txt', 'file5.txt']

print(sorted(l))
# ['file1.txt', 'file10.txt', 'file5.txt']

print(sorted(l, key=lambda s: int(re.search(r'd+', s).group())))
# ['file1.txt', 'file5.txt', 'file10.txt']

Si le nombre d’éléments est petit, vous n’avez pas trop à vous inquiéter, mais il est plus efficace de générer un objet d’expression régulière avec compile() et de l’utiliser.

p = re.compile(r'd+')
print(sorted(l, key=lambda s: int(p.search(s).group())))
# ['file1.txt', 'file5.txt', 'file10.txt']

Plus d’un nombre dans une chaîne

search() ne renvoie que la première correspondance.

s = '100file5.txt'

print(re.search(r'd+', s).group())
# 100

findall() renvoie toutes les pièces correspondantes sous forme de liste.

print(re.findall(r'd+', s))
# ['100', '5']

print(re.findall(r'd+', s)[1])
# 5

Si vous entourez des parties d’un motif entre (), vous ne pouvez extraire que cette partie avec la méthode groups().

Par exemple, le modèle file(d+) extrait  » de ‘file’. Notez qu’il renvoie un tuple même s’il n’y a qu’une seule partie correspondante.

print(re.search(r'file(d+)', s).groups())
# ('5',)

print(re.search(r'file(d+)', s).groups()[0])
# 5

(d+). extraits de ..

print(re.search(r'(d+).', s).groups()[0])
# 5

Exemples:

l = ['100file10.txt', '100file1.txt', '100file5.txt']

print(sorted(l, key=lambda s: int(re.findall(r'd+', s)[1])))
# ['100file1.txt', '100file5.txt', '100file10.txt']

print(sorted(l, key=lambda s: int(re.search(r'file(d+)', s).groups()[0])))
# ['100file1.txt', '100file5.txt', '100file10.txt']

print(sorted(l, key=lambda s: int(re.search(r'(d+).', s).groups()[0])))
# ['100file1.txt', '100file5.txt', '100file10.txt']
p = re.compile(r'file(d+)')
print(sorted(l, key=lambda s: int(p.search(s).groups()[0])))
# ['100file1.txt', '100file5.txt', '100file10.txt']

Certains éléments n’ont pas de numéro dans une chaîne

Si les chaînes de tous les éléments contiennent des nombres, il n’y a pas de problème, mais si ce n’est pas le cas, vous devriez envisager le cas d’aucune correspondance.

l = ['file10.txt', 'file1.txt', 'file5.txt', 'file.txt']

# print(sorted(l, key=lambda s:int(re.search(r'd+', s).group())))
# AttributeError: 'NoneType' object has no attribute 'group'

Par exemple, définissez la fonction suivante. Le premier paramètre est une chaîne, le second est un objet d’expression régulière et le troisième est la valeur de retour si elle ne correspond pas.

def extract_num(s, p, ret=0):
    search = p.search(s)
    if search:
        return int(search.groups()[0])
    else:
        return ret

Le résultat est le suivant. Le modèle a besoin de () car il utilise des groupes().

p = re.compile(r'(d+)')

print(extract_num('file10.txt', p))
# 10

print(extract_num('file.txt', p))
# 0

print(extract_num('file.txt', p, 100))
# 100

Le troisième argument est facultatif.

Vous pouvez spécifier cette fonction pour le paramètre clé de sort() ou sorted().

print(sorted(l, key=lambda s: extract_num(s, p)))
# ['file.txt', 'file1.txt', 'file5.txt', 'file10.txt']

print(sorted(l, key=lambda s: extract_num(s, p, float('inf'))))
# ['file1.txt', 'file5.txt', 'file10.txt', 'file.txt']

Si vous voulez mettre des éléments qui ne contiennent pas de valeurs numériques à la fin de l’ordre croissant, vous pouvez utiliser l’infini inf.

Si une chaîne contient plusieurs nombres, modifiez l’objet d’expression régulière.

l = ['100file10.txt', '100file1.txt', '100file5.txt', '100file.txt']

p = re.compile(r'file(d+)')
print(sorted(l, key=lambda s: extract_num(s, p)))
# ['100file.txt', '100file1.txt', '100file5.txt', '100file10.txt']

print(sorted(l, key=lambda s: extract_num(s, p, float('inf'))))
# ['100file1.txt', '100file5.txt', '100file10.txt', '100file.txt']