В чем разница между sorted(list)
против 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]
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]
После некоторой обратной связи я решил, что желателен другой тест с другими характеристиками. Здесь я предоставляю один и тот же случайно упорядоченный список длиной 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.
Poke также запустил свой собственный код, вот код:
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"