Common List Operations

Beyond creating and indexing, the list type exposes a small, well-chosen set of operations that show up in every real program: sorting, searching, counting, joining, splitting, and reducing. Most of these come as either a method that mutates the list or a free function that returns a new value, and knowing both forms lets you pick the right tool for each situation.

Sorting is probably the most common operation. list.sort() sorts the list in place and returns None; sorted(list) returns a new sorted list without touching the original. Both accept a key callable for custom orderings and a reverse=True flag. The sort is stable, meaning items that compare equal keep their original order — this property is subtly important when you sort by multiple fields.

Searching is a second major theme. x in items is the most readable membership test; items.index(x) locates an item and raises if absent; items.count(x) tells you how often it appears. All three are O(n); if you need fast lookups on a large list, convert it to a set or dict first.

Finally, aggregating is where Python really shines. The built-ins sum, min, max, any and all accept any iterable and reduce it to a single value. Combined with a generator expression, they replace dozens of lines of imperative code: sum(n for n in nums if n > 0) is both shorter and clearer than the equivalent for-loop.

Sorting and searching

A key function is called once per element and its return value is what gets compared. Sort people by age with people.sort(key=lambda p: p.age). Sort strings case-insensitively with key=str.casefold. For multi-key sorts, rely on stability: sort by the secondary key first, then by the primary key.

bisect from the standard library gives you O(log n) search and insertion on an already-sorted list. It is the right tool when you maintain a sorted list over time (for example, a leaderboard).

Combining and reducing

list1 + list2 returns a new concatenated list; list1 * 3 repeats. " ".join(strings) is the canonical way to collapse a list of strings into one string. For the reverse, text.split() returns a list.

functools.reduce generalizes sum/min/max when the combining step is custom. In practice you reach for it rarely; 90% of reductions are one of the built-ins or a comprehension.

The everyday toolbox for list operations.

ToolPurpose
list.sort(key=..., reverse=...)
method
Sorts the list in place; stable.
sorted(iterable, key=...)
built-in
Returns a new sorted list without mutating input.
list.count(x)
method
Counts occurrences of x.
list.index(x)
method
Finds the first index of x (raises if absent).
sum(iterable, start=0)
built-in
Adds items of an iterable.
any(iterable)
built-in
True if any item is truthy.
str.join(iterable)
method
Concatenates strings with a separator.
bisect.insort
standard-library function
Inserts into a sorted list in O(log n).

Common List Operations code example

The script below runs a small grading exercise so every operation has a purpose.

# Lesson: Common List Operations
from bisect import insort

scores = [72, 95, 88, 61, 95, 84, 73]
names = ["ana", "ben", "cai", "dev", "eli", "fay", "gio"]

sorted_scores = sorted(scores, reverse=True)
names_by_score = sorted(zip(scores, names), reverse=True)

top = sorted_scores[0]
appearances = scores.count(top)
first_top_name = names[scores.index(top)]

passed = [s for s in scores if s >= 70]
average = sum(scores) / len(scores)

joined = ", ".join(f"{n}:{s}" for s, n in names_by_score)

leaderboard: list[int] = []
for s in scores:
    insort(leaderboard, s)   # kept sorted the cheap way

print("sorted desc:", sorted_scores)
print("by score:   ", names_by_score)
print("top score:  ", top, "held by:", appearances)
print("first top:  ", first_top_name)
print("passed:     ", passed)
print("average:    ", round(average, 2))
print("joined:     ", joined)
print("leaderboard:", leaderboard)

The script makes eight common operations visible:

1) `sorted(..., reverse=True)` never mutates the input; handy when you still need the raw order.
2) Zipping two lists and sorting the result is the canonical way to keep parallel data aligned.
3) `count` and `index` share an O(n) scan; call them once and reuse the result.
4) `bisect.insort` keeps a list sorted cheaply as new items arrive.

Practice sorting with a key and summarizing with a built-in.

# Example A: case-insensitive sort
words = ["Apple", "banana", "apricot"]
print(sorted(words, key=str.casefold))

# Example B: reduce with a condition
nums = [3, -1, 4, -2, 5]
positive_sum = sum(n for n in nums if n > 0)
print(positive_sum)

Confirm the behaviors that matter most.

assert sorted([3, 1, 2]) == [1, 2, 3]
assert [1, 2] + [3] == [1, 2, 3]
assert [1, 2].count(1) == 1 and [1, 1, 2].count(1) == 2
assert "-".join(["a", "b"]) == "a-b"

The script prints:

sorted desc: [95, 95, 88, 84, 73, 72, 61]
by score:    [(95, 'eli'), (95, 'ben'), (88, 'cai'), (84, 'fay'), (73, 'gio'), (72, 'ana'), (61, 'dev')]
top score:   95 held by: 2
first top:   ben
passed:      [72, 95, 88, 84, 73]
average:     81.14
joined:      eli:95, ben:95, cai:88, fay:84, gio:73, ana:72, dev:61
leaderboard: [61, 72, 73, 84, 88, 95, 95]