← Home

089. Sorted() And Sort()

Control the order of lists with flexible sorting

089. Sorted() And Sort()

He displays the top 5 memory hogs. He sorts the process list with .sort() — accidentally modifying the original list. The next part of the program that iterates processes now sees them in RAM order, not the original order it expected.

The fix: use sorted() which returns a new list.

processes = [...]   # original list

# Bad: mutates processes in-place
processes.sort(key=lambda p: p["rss_mb"], reverse=True)

# Good: leaves original intact, returns a new sorted list
top5 = sorted(processes, key=lambda p: p["rss_mb"], reverse=True)[:5]

He also builds a multi-key sort: RAM descending, then name alphabetically for ties.

ranked = sorted(
    processes,
    key=lambda p: (-p["rss_mb"], p["name"])  # negative for descending
)

💡 Fun fact: Python uses Timsort, an algorithm invented by Tim Peters in 2002 specifically for Python. Timsort is a hybrid of merge sort and insertion sort that exploits real-world patterns in data (such as partially sorted runs). It was so effective that Java adopted it for Arrays.sort() in Java 7, and Android’s Arrays.sort() uses it too.

⚠️ Watch out: The most dangerous sorted vs .sort() mistake is calling .sort() when you need the original order preserved elsewhere in your program. .sort() modifies the list in-place and returns None — so result = my_list.sort() sets result to None, not the sorted list. This is a silent data loss bug.

🤔 Think about it: Python’s sort is stable — equal elements keep their original relative order. This property enables a powerful technique: sort by secondary key first, then sort by primary key, and stability preserves the secondary ordering within tied primary groups. Can you think of a real-world example where this “sort-then-sort” pattern would be useful?

Learning objectives

  • Sort lists with sorted() and a key function
  • Sort in descending order with reverse=True
  • Implement multi-key sort with tuple keys

Key concepts

  • sorted
  • sort
  • key function
  • reverse
  • stable sort

Try it

Concept detail

sorted(iterable) → returns a NEW sorted list (original unchanged). list.sort() → sorts the list IN-PLACE, returns None.

WHY prefer sorted() over .sort() in most cases: original = [3, 1, 2] new_list = sorted(original) # original unchanged — safe original.sort() # original mutated — may surprise other code

Key function — sort by a computed value: sorted(items, key=lambda x: x[“score”]) sorted(items, key=lambda x: x[“name”].lower()) # case-insensitive

Reverse order: sorted(items, reverse=True) sorted(items, key=lambda x: x[“score”], reverse=True)

Multi-key sort — tuple key: sorted(items, key=lambda x: (x[“score”], x[“name”])) # primary: score ascending; tie-break: name ascending

Reverse one key in a multi-key sort — negate numeric values: sorted(items, key=lambda x: (-x[“score”], x[“name”])) # primary: score DESCENDING; tie-break: name ascending

Stable sort: Python’s Timsort preserves the original order of equal elements. This means you can sort by a secondary key first, then the primary key, and stability keeps the secondary order within tied primary groups.

sorted() works on ANY iterable (list, tuple, dict, generator). list.sort() only works on lists.

Solution

def top_players(players, n):
    sorted_players = sorted(players, key=lambda p: p["score"], reverse=True)
    return sorted_players[:n]

def sort_by_name(players):
    return sorted(players, key=lambda p: p["name"])

def sort_multi(items):
    return sorted(items, key=lambda x: (-x["score"], x["name"]))

Tests

PLAYERS = [
    {"name": "Alice", "score": 85},
    {"name": "Bob",   "score": 92},
    {"name": "Carol", "score": 78},
    {"name": "Dave",  "score": 92},
]

def test_top_players_first():
    result = top_players(PLAYERS, 1)
    assert result[0]["score"] == 92

def test_top_players_count():
    result = top_players(PLAYERS, 2)
    assert len(result) == 2
    assert all(p["score"] >= 85 for p in result)

def test_top_players_not_mutated():
    original_first = PLAYERS[0]["name"]
    top_players(PLAYERS, 2)
    assert PLAYERS[0]["name"] == original_first

def test_sort_by_name():
    result = sort_by_name(PLAYERS)
    names = [p["name"] for p in result]
    assert names == sorted(names)

def test_sort_by_name_first():
    result = sort_by_name(PLAYERS)
    assert result[0]["name"] == "Alice"

def test_sort_multi_top():
    result = sort_multi(PLAYERS)
    assert result[0]["score"] == 92

def test_sort_multi_tiebreak():
    result = sort_multi(PLAYERS)
    tied = [p for p in result if p["score"] == 92]
    assert tied[0]["name"] < tied[1]["name"]  # Bob before Dave alphabetically

Resources