Яка різниця між sorted(list)
vs list.sort()
?
list.sort
вимкнення списку на місці та повернення None
sorted
бере будь-який ітерабельний і повертає новий список, відсортований.
sorted
еквівалентно цій реалізації Python, але вбудована CPython функція повинна працювати помірно швидше, як це написано на 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
коли використовувати який?
- Використовуйте,
list.sort
коли ви не бажаєте зберігати оригінальний порядок сортування (таким чином, ви зможете повторно використовувати список на місці в пам’яті.) І коли ви є єдиним власником списку (якщо цей список наданий іншим кодом, і ви вимкніть його, ви можете ввести помилки, де використовується цей список.)
- Використовуйте,
sorted
коли ви хочете зберегти початковий порядок сортування або коли ви хочете створити новий список, яким володіє лише ваш місцевий код.
Чи можна отримати вихідні позиції списку після list.sort ()?
Ні - якщо ви самі не зробили копію, ця інформація втрачається, оскільки сортування робиться на місці.
"А що швидше? І наскільки швидше?"
Для ілюстрації покарання створення нового списку використовуйте модуль timeit, ось наша настройка:
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
"""
І ось наші результати щодо списку випадково розташованих 10000 цілих чисел, як ми бачимо тут, ми спростували міф про створення старих списків :
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]
Пітон 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]
Після деяких відгуків, я вирішив, що ще один тест буде бажаним з різними характеристиками. Тут я надаю той самий випадково упорядкований список довжиною 100 000 за кожну ітерацію 1000 разів.
import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""
Я інтерпретую цю різницю різного роду від копіювання, згаданого Мартійна, але це не домінує до моменту, зазначеного в більш старій більш популярній відповіді тут, тут збільшення часу становить лише приблизно 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]
Я також запустив вищезазначене на набагато менший сорт і побачив, що нова sorted
версія копії все ще займає приблизно 2% більше часу роботи на 1000 довжини.
Пок також запустив власний код, ось код:
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))
Він знайшов для 1000000 сорти довжини (пробіг 100 разів) аналогічний результат, але лише приблизно на 5% збільшення часу, ось результат:
10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655
Висновок:
Список великих розмірів, відсортований із sorted
створенням копії, ймовірно, буде домінувати у відмінностях, але саме сортування домінує над операцією, а організація коду навколо цих відмінностей буде передчасною оптимізацією. Я б використовував, sorted
коли мені потрібен новий відсортований список даних, і я б використовував, list.sort
коли мені потрібно сортувати список на місці, і нехай це визначає моє використання.
sorted()
на аргумент рядка, але думаєте, що це список, ви отримаєте результат списку, а не рядок : неsorted("abcd", reverse=True)
дає['d', 'c', 'b', 'a']
"dcba"