Чим відрізняється `sorted (list)` vs `list.sort ()`?


194

list.sort()сортує список та замінює оригінальний список, тоді як sorted(list)повертає відсортовану копію списку, не змінюючи оригінальний список.

  • Коли один віддає перевагу іншому?
  • Що є більш ефективним? На скільки?
  • Чи може після повернення списку повернутися до несортованого стану list.sort()?

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.
— користувач1767754

45

Яка різниця між 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коли мені потрібно сортувати список на місці, і нехай це визначає моє використання.


4
Установка генератора хороша, але я б не зробив висновок, що ви занадто швидко розгромили міф. Залишається фактом, що sorted()потрібно виділити новий об'єкт списку та скопіювати посилання; решта кодових шляхів однакові. Подивіться, чи можна проводити ті ж тести з більшими списками. Порівняйте це з лише створенням копій списків і подивіться, чи зможете ви повторити знайдені відмінності тощо
— Martijn Pieters

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 () метод виступає як функція або кажуть, що він бере аргументи в ньому.

Ви повинні зберігати значення відсортованого (списку) у змінній явно.

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


"Функція .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]

Дякуємо, що детальніше показали оригінал та копію
— Брендан Меткалф

0

Примітка: Найпростіша різниця між sort () та sorted () - це: sort () не повертає жодного значення, а sorted () повертає список, який можна повторити.

sort () не повертає жодного значення.

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

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

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

Крім того, ви можете також використовувати вбудовану функцію Python, відсортовану () для тих же цілей. відсортована функція повернення відсортованого списку

 list=sorted(list, key=..., reverse=...)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.