Чим відрізняється `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.