В чем разница между 'sorted (list)' vs 'list.sort()'?

list.sort() сортирует список и сохраняет отсортированный список, а sorted(list) возвращает отсортированную копию списка без изменения исходного списка.

  • Но когда использовать что?
  • А что быстрее? И насколько быстрее?
  • Можно ли восстановить список исходных позиций после list.sort()?

Ответ 1

sorted() возвращает новый отсортированный список, оставляя исходный список незатронутым. list.sort() сортирует список на месте, мутирует индексы списка и возвращает None (как и все операции на месте).

sorted() работает над любыми итерабельными, а не только списками. Строки, кортежи, словари (вы получите ключи), генераторы и т.д., Возвращая список, содержащий все элементы, отсортированные.

  • Используйте list.sort(), если вы хотите изменить список, sorted(), когда вы хотите вернуть новый отсортированный объект. Используйте sorted(), если вы хотите отсортировать что-то, что является итерируемым, а не список.

  • Для списков list.sort() быстрее, чем sorted(), потому что ему не нужно создавать копию. Для любого другого итеративного выбора у вас нет выбора.

  • Нет, вы не можете получить исходные позиции. После того, как вы вызвали list.sort(), первоначальный порядок исчез.

Ответ 2

В чем разница между 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 если вы хотите сохранить исходный порядок сортировки или когда вы хотите создать новый список, которому владеет только ваш локальный код.

Можно ли восстановить список исходных позиций после списка.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)
"""

Я интерпретирую эту большую разницу в размерах, исходящую от копирования, упомянутого Martijn, но он не доминирует в точке, указанной в более старом более популярном ответе здесь, здесь увеличение времени составляет лишь около 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 когда мне нужно было отсортировать список на месте, и пусть это определит мое использование.

Ответ 3

Основное отличие состоит в том, что sorted(some_list) возвращает новый list:

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

и some_list.sort(), сортирует список на месте:

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

Примечание, так как a.sort() ничего не возвращает, print a.sort() будет печатать None.


Можно ли восстановить исходные позиции списка после списка .sort()?

Нет, поскольку он изменяет исходный список.

Ответ 4

Функция.sort() сохраняет значение нового списка непосредственно в переменной списка; так что ответ на третий вопрос будет НЕТ. Также, если вы это сделаете с помощью отсортированного (списка), вы можете использовать его, потому что он не сохраняется в переменной списка. Также иногда метод.sort() действует как функция или говорит, что в нем принимают аргументы.

Вы должны сохранить значение отсортированного (списка) в переменной явно.

Также для короткой обработки данных скорость не будет иметь разницы; но для длинных списков; вам следует использовать метод.sort() для быстрой работы; но снова вы столкнетесь с необратимыми действиями.

Ответ 5

Вот несколько простых примеров, чтобы увидеть разницу в действии:

См. Список номеров здесь:

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

При вызове, sorted по этому списку, sorted сделает копию списка. (Значение вашего исходного списка останется без изменений.)

Посмотрим.

sorted(nums)

возвращается

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

Глядя на nums снова

nums

Мы видим исходный список (неизмененный и НЕ отсортированный.). sorted не изменила первоначальный список

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

Используя тот же список nums и применяя функцию sort на нем, измените фактический список.

Посмотрим.

Начиная с нашего списка nums чтобы убедиться, что контент все тот же.

nums

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

nums.sort()

Теперь исходный список nums изменен и, глядя на числа, которые мы видим, наш первоначальный список изменился и теперь отсортирован.

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

Ответ 6

Примечание. Простейшей разницей между sort() и sorted() является: sort() не возвращает никакого значения, а sorted() возвращает итерируемый список.

sort() не возвращает никакого значения.

Метод sort() просто сортирует элементы данного списка в определенном порядке - по возрастанию или по убыванию, не возвращая никакого значения.

Синтаксис метода sort():

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

В качестве альтернативы вы также можете использовать встроенную функцию Python sorted() для той же цели. отсортированный список результатов

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