What is the difference between `sorted(list)` vs `list.sort()`?
Asked Answered
A

7

295

list.sort() sorts the list and replaces the original list, whereas sorted(list) returns a sorted copy of the list, without changing the original list.

  • When is one preferred over the other?
  • Which is more efficient? By how much?
  • Can a list be reverted to the unsorted state after list.sort() has been performed?

Please use Why do these list operations (methods) return None, rather than the resulting list? to close questions where OP has inadvertently assigned the result of .sort(), rather than using sorted or a separate statement. Proper debugging would reveal that .sort() had returned None, at which point "why?" is the remaining question.

Ashur answered 16/3, 2014 at 20:16 Comment(2)
Beware if you (accidentally) call sorted() on a string argument but think it's a list, you get a list result, not a string: sorted("abcd", reverse=True) gives ['d', 'c', 'b', 'a'] not "dcba"Sec
Note for folks looking for duplicates: A number of questions related to list.sort() returning None, not a new list, are being duped here, when they'd be better off duped to the more specific Why does “return list.sort()” return None, not the list?.Chassepot
I
435

sorted() returns a new sorted list, leaving the original list unaffected. list.sort() sorts the list in-place, mutating the list indices, and returns None (like all in-place operations).

sorted() works on any iterable, not just lists. Strings, tuples, dictionaries (you'll get the keys), generators, etc., returning a list containing all elements, sorted.

  • Use list.sort() when you want to mutate the list, sorted() when you want a new sorted object back. Use sorted() when you want to sort something that is an iterable, not a list yet.

  • For lists, list.sort() is faster than sorted() because it doesn't have to create a copy. For any other iterable, you have no choice.

  • No, you cannot retrieve the original positions. Once you called list.sort() the original order is gone.

Instance answered 16/3, 2014 at 20:21 Comment(1)
In general, when a python function returns None, it is a sign, that the operations are done in place, that's why, when you want to print list.sort() it returns None.Barcarole
B
67

What is the difference between sorted(list) vs list.sort()?

  • list.sort mutates the list in-place & returns None
  • sorted takes any iterable & returns a new list, sorted.

sorted is equivalent to this Python implementation, but the CPython builtin function should run measurably faster as it is written in 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

when to use which?

  • Use list.sort when you do not wish to retain the original sort order (Thus you will be able to reuse the list in-place in memory.) and when you are the sole owner of the list (if the list is shared by other code and you mutate it, you could introduce bugs where that list is used.)
  • Use sorted when you want to retain the original sort order or when you wish to create a new list that only your local code owns.

Can a list's original positions be retrieved after list.sort()?

No - unless you made a copy yourself, that information is lost because the sort is done in-place.

"And which is faster? And how much faster?"

To illustrate the penalty of creating a new list, use the timeit module, here's our setup:

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
"""

And here's our results for a list of randomly arranged 10000 integers, as we can see here, we've disproven an older list creation expense myth:

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]

After some feedback, I decided another test would be desirable with different characteristics. Here I provide the same randomly ordered list of 100,000 in length for each iteration 1,000 times.

import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""

I interpret this larger sort's difference coming from the copying mentioned by Martijn, but it does not dominate to the point stated in the older more popular answer here, here the increase in time is only about 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]

I also ran the above on a much smaller sort, and saw that the new sorted copy version still takes about 2% longer running time on a sort of 1000 length.

Poke ran his own code as well, here's the code:

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))

He found for 1000000 length sort, (ran 100 times) a similar result, but only about a 5% increase in time, here's the output:

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

Conclusion:

A large sized list being sorted with sorted making a copy will likely dominate differences, but the sorting itself dominates the operation, and organizing your code around these differences would be premature optimization. I would use sorted when I need a new sorted list of the data, and I would use list.sort when I need to sort a list in-place, and let that determine my usage.

Bonnard answered 16/3, 2014 at 20:44 Comment(1)
The generator setup is nice, but I wouldn't draw the conclusion that you busted a myth too quickly. The fact remains that sorted() has to allocate a new list object and copy the references; the rest of the code paths are identical. See if you can run the same tests with larger lists. Compare it with just creating copies of lists and see if you can replicate the differences you found, etc.Instance
M
16

The main difference is that sorted(some_list) returns a new list:

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

and some_list.sort(), sorts the list in place:

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

Note that since a.sort() doesn't return anything, print a.sort() will print None.


Can a list original positions be retrieved after list.sort()?

No, because it modifies the original list.

Message answered 16/3, 2014 at 20:19 Comment(2)
print a.sort() won't print anything.Typehigh
It will print None, I will clarify that.Message
O
5

Here are a few simple examples to see the difference in action:

See the list of numbers here:

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

When calling sorted on this list, sorted will make a copy of the list. (Meaning your original list will remain unchanged.)

Let's see.

sorted(nums)

returns

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

Looking at the nums again

nums

We see the original list (unaltered and NOT sorted.). sorted did not change the original list

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

Taking the same nums list and applying the sort function on it, will change the actual list.

Let's see.

Starting with our nums list to make sure, the content is still the same.

nums

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

nums.sort()

Now the original nums list is changed and looking at nums we see our original list has changed and is now sorted.

nums
[-3, 1, 2, 4, 5, 7, 8, 14]
Oratorio answered 30/10, 2018 at 19:12 Comment(1)
Thank you for showing the original vs. copy in more depthLietman
W
5

Note: Simplest difference between sort() and sorted() is: sort() doesn't return any value while, sorted() returns an iterable list.

sort() doesn't return any value.

The sort() method just sorts the elements of a given list in a specific order - Ascending or Descending without returning any value.

The syntax of sort() method is:

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

Alternatively, you can also use Python's in-built function sorted() for the same purpose. sorted function return sorted list

 list=sorted(list, key=..., reverse=...)
Willumsen answered 6/12, 2018 at 13:4 Comment(1)
list is a type, this might be confusing, list should have another name in your example (e.g. my_list)Ative
B
1

The .sort() function stores the value of new list directly in the list variable; so answer for your third question would be NO. Also if you do this using sorted(list), then you can get it use because it is not stored in the list variable. Also sometimes .sort() method acts as function, or say that it takes arguments in it.

You have to store the value of sorted(list) in a variable explicitly.

Also for short data processing the speed will have no difference; but for long lists; you should directly use .sort() method for fast work; but again you will face irreversible actions.

Bugbear answered 1/4, 2018 at 14:53 Comment(5)
"The .sort() function stores the value of new list directly in the list variable" Huh? What new list? There's no new list. The list.sort() method sorts the list object in-place.Congratulation
Also, what is this supposed to mean? "sometimes .sort() method acts as function, or say that it takes arguments in it."Congratulation
What i mean by new list is the modified list and .sort() just stores that modified list into that same variable.Bugbear
Yes, absolutely sometimes .sort() method takes argument, and act as function. Also we call it method because it is an attribute of list datatype.Bugbear
If there is some sort of mistake in my concept then tell me, i will look for it and will improve my concepts, and my answer too. ThanksBugbear
I
1

With list.sort() you are altering the list variable but with sorted(list) you are not altering the variable.

Using sort:

list = [4, 5, 20, 1, 3, 2]
list.sort()
print(list)
print(type(list))
print(type(list.sort())

Should return this:

[1, 2, 3, 4, 5, 20]
<class 'NoneType'>

But using sorted():

list = [4, 5, 20, 1, 3, 2]
print(sorted(list))
print(list)
print(type(sorted(list)))

Should return this:

[1, 2, 3, 4, 5, 20]
[4, 5, 20, 1, 3, 2]
<class 'list'>
Immigration answered 27/7, 2022 at 15:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.