DEV Community

Erik Anderson
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]
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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!

Discussion (0)