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

194

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

  • Когда один предпочтительнее другого?
  • Что является более эффективным? На сколько?
  • Можно ли вернуть список в несортированное состояние после list.sort()выполнения?
Alvas
источник
4
Остерегайтесь, если вы (случайно) вызываете sorted()строковый аргумент, но думаете, что это список, вы получаете результат списка, а не строку : sorted("abcd", reverse=True)дает ['d', 'c', 'b', 'a']не"dcba"
smci

Ответы:

317

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

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

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

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

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

Мартейн Питерс
источник
6
В общем, когда функция python возвращается None, это признак того, что операции выполнены на месте, поэтому, когда вы хотите напечатать, list.sort()она возвращает None.
user1767754
45

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

Аарон Холл
источник
4
Генераторная установка хороша, но я бы не сделал вывод, что ты слишком быстро разрушил миф. Остается факт, что sorted()нужно выделить новый объект списка и скопировать ссылки; остальные пути кода идентичны. Посмотрите, сможете ли вы запустить те же тесты с большими списками. Сравните это только с созданием копий списков и посмотрите, сможете ли вы воспроизвести найденные различия и т. Д.
Мартин Питерс
11

Основное отличие в том, что 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's modified

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


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

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

Кристиан
источник
1
print a.sort()не буду ничего печатать.
Бурхан Халид
1
Он напечатает None, я уточню это.
Кристиан
1

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

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

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

Vicrobot
источник
Msgstr "Функция .sort () сохраняет значение нового списка прямо в переменной списка" А? Какой новый список? Там нет нового списка. list.sort()Метод сортирует список объектов на месте.
PM 2Ring
Кроме того, что это должно означать? «Иногда метод .sort () действует как функция или говорит, что принимает в нем аргументы.»
PM 2Ring
Под новым списком я подразумеваю измененный список, а .sort () просто сохраняет этот измененный список в той же самой переменной.
Vicrobot,
Да, абсолютно иногда .sort()метод принимает аргумент и действует как функция. Также мы называем это методом, потому что это атрибут типа списка.
Vicrobot
Если в моей концепции есть какая-то ошибка, то скажите мне, я поищу ее и улучшу свои концепции, и мой ответ тоже. Спасибо
Vicrobot
1

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

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

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
[-3, 1, 2, 4, 5, 7, 8, 14]
Stryker
источник
Спасибо, что показали оригинал против копии более подробно
Брендан Меткалф
0

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

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

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

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

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

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

 list=sorted(list, key=..., reverse=...)
Проеш Бхумик
источник