В чем разница между "отсортированным(списком)" и "списком".сортировка ()`?


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

  • но когда какую использовать?
  • а что быстрее? И насколько быстрее?
  • можно ли восстановить исходные позиции списка после list.sort()?
4 110

4 ответа:

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

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

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

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

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

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

  • list.sort изменяет список на месте и возвращает None
  • sorted принимает любой iterable и возвращает новый список, отсортированный.

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

можно ли получить исходные позиции списка после списка.сортировка ()?

нет - если вы не сделали копию себе, эта информация будет потеряна, потому что сортировка выполняется на месте.

"а что быстрее? И насколько быстрее?"

чтобы проиллюстрировать штраф за создание нового списка, используйте модуль 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 сортировка длины, (ran 100 times) аналогичный результат, но только около 5% увеличения времени, вот результат:

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

вывод:

большой размер списка сортируется с sorted создание копии, скорее всего, будет доминировать над различиями, но сама сортировка доминирует над операцией, и организация вашего кода вокруг этих различий будет преждевременной оптимизацией. Я бы использовал sorted когда мне нужен новый отсортированный список данных, и я хотел бы использовать list.sort когда мне нужно отсортировать список на месте, и пусть это определяет мое использование.

главное отличие в том, что sorted(some_list) возвращает a новая 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.


можно ли получить исходные позиции списка после списка.сортировка ()?

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

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

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

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