Erik Anderson

Posted on

# A lesson in in-place sorting: the difference between sorted() and .sort() and why it matters.

I've been volunteering as a mentor on exercism.io. It's a website for doing mentored code exercises, and I promise it's not satanic in any way.

[Spoiler alert] If you'd prefer to attempt the problem before seeing the solution presented below, head over to exercism.io.

As I write up suggestions to students who have submitted solutions, I find myself writing things that other people might want to read. For that reason, I'm going to present a representative solution containing an issue that I addressed recently.

Briefly, the problem was to take a list of one player's video games scores and write three functions: One that returns the latest score, one that returns the personal best score, and one that returns a list of the three best scores in order.

First, here's the canonical solution, according to the mentor guidelines.

``````    def latest(scores):
return scores[-1]

def personal_best(scores):
return max(scores)

def personal_top_three(scores):
return sorted(scores, reverse=True)[:3]
``````

It's worth unpacking `personal_top_three()` as it's a bit dense.

`sorted(scores, reverse=True)` returns a sorted copy of the list in descending order. This then feeds into [:3], which selects the first three items (indices 0 through 2, inclusive) and returns them.

Now, here's a representative solution, which resembles some submissions I've seen.

``````def latest(scores):
return scores[-1]

def personal_best(scores):
return max(scores)

def personal_top_three(scores):
scores.sort(reverse=True)
return scores[:3]
``````

Take a moment and notice the differences.

It's a good solution, but there's an issue. Here's what I would say to the hypothetical student who wrote this.

First, I recommend being careful with `.sort()` because it changes the list `scores` in place, meaning that the values stored in the list `scores` will be re-arranged. This can cause unexpected behaviour if scores gets used elsewhere.

For example, imagine that someone called `personal_top_three(scores)` then called `latest(scores)`. In this case, `latest(scores)` might give unexpected results.

Unless you have a good reason to sort in place, I recommend used `sorted(scores)`, which returns a sorted copy of `scores`, leaving `scores` itself unchanged.
As an added bonus of using `sorted()` in `personal_best()`, it will allow you to have only one line of function body. Do you see why?

I hope you found this helpful, and that it piqued your interest in Exercism. I encourage you to try it out as a student, mentor, or both!