Quelle est la différence entre `sorted (list)` et `list.sort ()`?

194

list.sort()trie la liste et remplace la liste d'origine, tandis que sorted(list)renvoie une copie triée de la liste, sans modifier la liste d'origine.

  • Quand l'un est-il préféré à l'autre?
  • Qu'est-ce qui est le plus efficace? De combien?
  • Une liste peut-elle être remise à l'état non trié après list.sort()avoir été exécutée?
alvas
la source
4
Méfiez-vous si vous appelez (accidentellement) sorted()un argument de chaîne mais pensez que c'est une liste, vous obtenez un résultat de liste, pas une chaîne : sorted("abcd", reverse=True)donne ['d', 'c', 'b', 'a']pas"dcba"
smci

Réponses:

317

sorted()renvoie une nouvelle liste triée, laissant la liste d'origine inchangée. list.sort()trie la liste sur place , mute les index de la liste et renvoie None(comme toutes les opérations sur place).

sorted()fonctionne sur tout itérable, pas seulement sur des listes. Chaînes, tuples, dictionnaires (vous obtiendrez les clés), générateurs, etc., renvoyant une liste contenant tous les éléments, triés.

  • À utiliser list.sort()lorsque vous souhaitez modifier la liste, sorted()lorsque vous souhaitez récupérer un nouvel objet trié. Utilisez sorted()lorsque vous voulez trier quelque chose qui est un itératives, pas une liste encore .

  • Pour les listes, list.sort()c'est plus rapide que sorted()parce qu'il n'est pas nécessaire de créer une copie. Pour tout autre itérable, vous n'avez pas le choix.

  • Non, vous ne pouvez pas récupérer les positions d'origine. Une fois que vous avez appelé, list.sort()la commande d'origine est partie.

Martijn Pieters
la source
6
En général, lorsqu'une fonction python retourne None, c'est un signe, que les opérations sont effectuées sur place, c'est pourquoi, lorsque vous souhaitez imprimer list.sort()elle retourne None.
user1767754
45

Quelle est la différence entre sorted(list)vs list.sort()?

  • list.sort mute la liste sur place et retourne None
  • sorted prend tout itérable et renvoie une nouvelle liste, triée.

sorted est équivalent à cette implémentation Python, mais la fonction intégrée CPython devrait s'exécuter beaucoup plus rapidement car elle est écrite en C:

def sorted(iterable, key=None):
    new_list = list(iterable)    # make a new list
    new_list.sort(key=key)       # sort it
    return new_list              # return it

quand utiliser lequel?

  • À utiliser list.sortlorsque vous ne souhaitez pas conserver l'ordre de tri d'origine (vous pourrez ainsi réutiliser la liste en place en mémoire.) Et lorsque vous êtes l'unique propriétaire de la liste (si la liste est partagée par un autre code et que vous muter, vous pourriez introduire des bogues là où cette liste est utilisée.)
  • À utiliser sortedlorsque vous souhaitez conserver l'ordre de tri d'origine ou lorsque vous souhaitez créer une nouvelle liste que seul votre code local possède.

Les positions d'origine d'une liste peuvent-elles être récupérées après list.sort ()?

Non - sauf si vous avez fait une copie vous-même, ces informations sont perdues car le tri est effectué sur place.

"Et lequel est le plus rapide? Et combien plus rapide?"

Pour illustrer la peine de créer une nouvelle liste, utilisez le module timeit, voici notre configuration:

import timeit
setup = """
import random
lists = [list(range(10000)) for _ in range(1000)]  # list of lists
for l in lists:
    random.shuffle(l) # shuffle each list
shuffled_iter = iter(lists) # wrap as iterator so next() yields one at a time
"""

Et voici nos résultats pour une liste de 10000 entiers arrangés aléatoirement, comme nous pouvons le voir ici, nous avons réfuté un ancien mythe des dépenses de création de liste :

Python 2.7

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[3.75168503401801, 3.7473005310166627, 3.753129180986434]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[3.702025591977872, 3.709248117986135, 3.71071034099441]

Python 3

>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[2.797430992126465, 2.796825885772705, 2.7744789123535156]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[2.675589084625244, 2.8019039630889893, 2.849375009536743]

Après quelques retours, j'ai décidé qu'un autre test serait souhaitable avec des caractéristiques différentes. Ici, je fournis la même liste aléatoire de 100 000 fois pour chaque itération 1 000 fois.

import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""

J'interprète la différence de ce type plus large provenant de la copie mentionnée par Martijn, mais elle ne domine pas au point indiqué dans la réponse plus ancienne plus populaire ici, ici l'augmentation du temps n'est que d'environ 10%

>>> timeit.repeat("lst[:].sort()", setup=setup, number = 10000)
[572.919036605, 573.1384446719999, 568.5923951]
>>> timeit.repeat("sorted(lst[:])", setup=setup, number = 10000)
[647.0584738299999, 653.4040515829997, 657.9457361929999]

J'ai également exécuté ce qui précède sur une sorte beaucoup plus petite, et j'ai vu que la nouvelle sortedversion de copie prend encore environ 2% de plus de temps d'exécution sur une sorte de longueur 1000.

Poke a également exécuté son propre code, voici le code:

setup = '''
import random
random.seed(12122353453462456)
lst = list(range({length}))
random.shuffle(lst)
lists = [lst[:] for _ in range({repeats})]
it = iter(lists)
'''
t1 = 'l = next(it); l.sort()'
t2 = 'l = next(it); sorted(l)'
length = 10 ** 7
repeats = 10 ** 2
print(length, repeats)
for t in t1, t2:
    print(t)
    print(timeit(t, setup=setup.format(length=length, repeats=repeats), number=repeats))

Il a trouvé pour un tri de longueur 1000000 (exécuté 100 fois) un résultat similaire, mais seulement une augmentation d'environ 5% du temps, voici le résultat:

10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655

Conclusion:

Une liste de grande taille triée avec sortedune copie dominera probablement les différences, mais le tri lui-même domine l'opération, et organiser votre code autour de ces différences serait une optimisation prématurée. J'utiliserais sortedquand j'ai besoin d'une nouvelle liste triée des données, et j'utiliserais list.sortquand j'ai besoin de trier une liste sur place, et laisser cela déterminer mon utilisation.

Salle Aaron
la source
4
La configuration du générateur est bien, mais je ne tirerais pas la conclusion que vous avez brisé un mythe trop rapidement. Il n'en reste pas moins qu'il sorted()faut allouer un nouvel objet liste et copier les références; le reste des chemins de code sont identiques. Voyez si vous pouvez exécuter les mêmes tests avec des listes plus grandes. Comparez-le avec la simple création de copies de listes et voyez si vous pouvez reproduire les différences que vous avez trouvées, etc.
Martijn Pieters
11

La principale différence est que sorted(some_list)renvoie un nouveaulist :

a = [3, 2, 1]
print sorted(a) # new list
print a         # is not modified

et some_list.sort(), trie la liste en place :

a = [3, 2, 1]
print a.sort() # in place
print a         # it's modified

Notez que puisque a.sort()ne renvoie rien, print a.sort()imprimera None.


Une liste de positions d'origine peut-elle être récupérée après list.sort ()?

Non, car cela modifie la liste d'origine.

Christian
la source
1
print a.sort()n'imprimera rien.
Burhan Khalid
1
Il imprimera None, je vais clarifier cela.
Christian
1

La fonction .sort () stocke la valeur de la nouvelle liste directement dans la variable de liste; la réponse à votre troisième question serait donc NON. De plus, si vous faites cela en utilisant trié (liste), vous pouvez l'utiliser car il n'est pas stocké dans la variable de liste. Parfois aussi, la méthode .sort () agit comme une fonction ou dit qu'elle contient des arguments.

Vous devez stocker la valeur de trié (liste) dans une variable de manière explicite.

Aussi pour le traitement de données court, la vitesse n'aura aucune différence; mais pour de longues listes; vous devez utiliser directement la méthode .sort () pour un travail rapide; mais encore une fois, vous serez confronté à des actions irréversibles.

Vicrobot
la source
"La fonction .sort () stocke la valeur de la nouvelle liste directement dans la variable de liste" Hein? Quelle nouvelle liste? Il n'y a pas de nouvelle liste. La list.sort()méthode trie l'objet de liste sur place.
PM 2Ring
Aussi, qu'est-ce que cela signifie? "Parfois, la méthode .sort () agit comme une fonction, ou dit qu'elle y prend des arguments."
PM 2Ring
Ce que j'entends par nouvelle liste est la liste modifiée et .sort () stocke simplement cette liste modifiée dans cette même variable.
Vicrobot
Oui, absolument parfois, la .sort()méthode prend un argument et agit comme une fonction. Nous l'appelons également méthode car il s'agit d'un attribut de type de données liste.
Vicrobot
S'il y a une sorte d'erreur dans mon concept, dites-moi, je vais le chercher et améliorer mes concepts, ainsi que ma réponse. Merci
Vicrobot
1

Voici quelques exemples simples pour voir la différence en action:

Consultez la liste des numéros ici:

nums = [1, 9, -3, 4, 8, 5, 7, 14]

Lors de l'appel sortedsur cette liste, sortedfera une copie de la liste. (Cela signifie que votre liste d'origine restera inchangée.)

Voyons voir.

sorted(nums)

Retour

[-3, 1, 4, 5, 7, 8, 9, 14]

Regardant à numsnouveau

nums

Nous voyons la liste d'origine (inchangée et NON triée). sortedn'a pas changé la liste d'origine

[1, 2, -3, 4, 8, 5, 7, 14]

Prendre la même numsliste et y appliquer la sortfonction changera la liste actuelle.

Voyons voir.

En commençant par notre numsliste pour vous en assurer, le contenu est toujours le même.

nums

[-3, 1, 4, 5, 7, 8, 9, 14]

nums.sort()

Maintenant, la liste nums originale est changée et en regardant nums, nous voyons que notre liste originale a changé et est maintenant triée.

nums
[-3, 1, 2, 4, 5, 7, 8, 14]
Stryker
la source
Merci d'avoir montré l'original par rapport à la copie plus en profondeur
Brendan Metcalfe
0

Remarque: la différence la plus simple entre sort () et sorted () est: sort () ne renvoie aucune valeur tandis que sorted () renvoie une liste itérative.

sort () ne renvoie aucune valeur.

La méthode sort () trie simplement les éléments d'une liste donnée dans un ordre spécifique - croissant ou décroissant sans renvoyer aucune valeur.

La syntaxe de la méthode sort () est:

list.sort(key=..., reverse=...)

Alternativement, vous pouvez également utiliser la fonction intégrée de Python sorted () dans le même but. fonction triée retour liste triée

 list=sorted(list, key=..., reverse=...)
Projesh Bhoumik
la source