Unit 2 • Lesson 6

Sorting and Ranking

Overview

Order by the value you mean, and remember that sorted returns a new list.

Beginner 20–25 min

What You Will Learn in This Lesson

By the end of this lesson, you will be able to:

  • Sort records by a field with key and reverse.
  • Avoid the .sort()-returns-None trap.
  • Break ties with a tuple key, including a descending number and an ascending name.
  • Take the top n with a slice, and give tied values the same rank.

Why This Matters

Most reports end in a ranking: the top five products, the lowest-scoring topics, the students who most need help. Getting the order right means sorting by the right field, in the right direction, with a sensible rule for ties — and not losing the list along the way. pandas’ sort_values and nlargest in unit 6 take the same arguments for the same reasons.

Step 1: Sorting by a field

Records do not have a natural order. key tells sorted which part of each one to compare.

1

key and reverse

key is a function applied to each item; its result is what gets compared. reverse=True puts the largest first.

rows = [{"name": "Ada", "score": 92}, {"name": "Alan", "score": 79}, {"name": "Grace", "score": 88}]

best = sorted(rows, key=lambda r: r["score"], reverse=True)
print([r["name"] for r in best])
2

sorted versus .sort()

sorted(x) returns a new list and leaves x alone. x.sort() reorders x itself and returns None. So names = names.sort() throws the list away.

names = ["Grace", "Ada", "Alan"]
print(sorted(names), names)

result = names.sort()
print(result, names)

Mini Practice #1: Lowest first

Try It Yourself

Print the names from lowest score to highest, then check that rows itself is still in its original order.

Press Run to see output

Step 2: Ties

Two rows with the same score come out in whatever order they went in. If the order matters, say what breaks the tie.

1

A tuple key

Tuples compare element by element, so key=lambda r: (r["score"], r["name"]) sorts by score and then by name within equal scores.

rows = [{"name": "Grace", "score": 88}, {"name": "Ada", "score": 88}, {"name": "Alan", "score": 79}]

print([r["name"] for r in sorted(rows, key=lambda r: (r["score"], r["name"]))])
2

Descending numbers, ascending names

reverse=True would flip both parts. Negating the number flips only the score: highest score first, and alphabetical among ties.

rows = [{"name": "Grace", "score": 88}, {"name": "Ada", "score": 88}, {"name": "Katherine", "score": 99}]

ranked = sorted(rows, key=lambda r: (-r["score"], r["name"]))
print([(r["name"], r["score"]) for r in ranked])

Mini Practice #2: Break the tie

Try It Yourself

Sort by score, highest first, with ties in alphabetical order by name.

Press Run to see output

Step 3: Top n and ranks

A ranking is a sort followed by either a slice or a numbering.

1

Slicing the top

Sort, then take [:n]. A slice longer than the list simply returns what there is, so asking for the top ten of a short list needs no special case.

scores = [92, 79, 88]
print(sorted(scores, reverse=True)[:2])
print(sorted(scores, reverse=True)[:10])
2

Equal scores, equal rank

Numbering the sorted list with enumerate gives tied students different ranks. The fairer rule (“competition ranking”) gives a tie the same rank, and the next student the rank after all the tied ones: 1, 2, 2, 4.

scores = sorted([92, 88, 88, 79], reverse=True)

ranks = []
for i, s in enumerate(scores):
    if i > 0 and s == scores[i - 1]:
        ranks.append(ranks[-1])
    else:
        ranks.append(i + 1)
print(list(zip(scores, ranks)))

Key idea: Sorting a column that is still text sorts it alphabetically — "100" before "20". Convert types (lesson 3) before sorting numbers.

Step 4: When to Use It

Top and bottom n

Leaderboards, the weakest topics, the largest orders: sorted with a key and reverse, then a slice.

sorted(rows, key=lambda r: r["score"], reverse=True)[:5]

Rankings people will read

A tuple key to break ties, and shared ranks for equal values.

When Not to Use It

Do not write x = x.sort() — it replaces your list with None. And do not sort a column that is still text: "100" comes before "20".

End-of-Lesson Exercises

Exercise 1: The top n names

Write top_names(rows, n) that returns the names of the n highest scorers, highest first.

sorted with a key and reverse, then take a slice. A slice longer than the list is not an error, which is why asking for five out of one works.

Press Run to try it, then Check my work to mark it.

Exercise 2: A fair ranking

Write rank(rows) returning a list of (rank, name, score) tuples, highest score first, with ties broken alphabetically by name. Tied scores share a rank, and the next score takes the rank after all the tied ones (1, 2, 2, 4).

Sort with key=lambda r: (-r["score"], r["name"]). Then walk it with enumerate: if the score equals the previous one, reuse the previous rank; otherwise the rank is i + 1.

Press Run to try it, then Check my work to mark it.