Intermediate16 min

Lambda, map, filter, and sorting

Anonymous functions and the functional built-ins used for sorting, ranking, and transforming records.

Why this matters in AI / ML / GenAI

Ranking retrieved chunks by score, sorting model results by latency, and applying a transform across a pandas column all use a `key=lambda` or a callable. It is the most common place a one-line function belongs.

lambda

lambda args: expression creates a function without naming it. It holds a single expression — no statements, no loops, no assignments — and returns its value automatically.

add = lambda a, b: a + b works but is bad style. If it deserves a name, use def; PEP 8 says so explicitly, and def gives a useful name in tracebacks.

Lambda's real home is as an argument: sorted(items, key=lambda x: x["score"]).

sorted with key and reverse

sorted(iterable, key=..., reverse=...) returns a new list; list.sort(...) sorts in place and returns None.

The key function is applied to each element and the results are compared. Sorting dicts by a field, strings by length, or tuples by their second item are all one-liners.

Multi-level sort: return a tuple from key. key=lambda r: (-r["score"], r["id"]) sorts by score descending, then id ascending. Negating a number is the standard trick for mixing directions.

Python's sort is stable: equal keys keep their original order, so you can sort by one field, then another, and the earlier order survives inside ties.

operator.itemgetter("score") and attrgetter("score") are faster, clearer alternatives to lambda for simple field access.

map, filter, and reduce

map(fn, iterable) applies a function to each item. filter(fn, iterable) keeps items where the function is truthy. Both return lazy iterators — wrap in list() to see them.

In modern Python a comprehension is usually preferred: [f(x) for x in xs] reads better than list(map(f, xs)). Reach for map when the function already exists by name.

functools.reduce(fn, iterable, initial) folds a sequence into one value. Most uses are better served by sum, min, max, or math.prod — keep reduce for genuinely custom accumulation.

min and max also accept key, which is the cleanest way to pick the best-scoring record.

Copy-paste examples

Copy into your own editor, or load one into the compiler below and press Run.

Ranking retrieved chunks

This is the reranking step of a RAG pipeline in one line.

chunks = [
    {"id": "c1", "score": 0.71, "text": "python basics"},
    {"id": "c3", "score": 0.94, "text": "rag pipelines"},
    {"id": "c2", "score": 0.71, "text": "vector search"},
]

ranked = sorted(chunks, key=lambda c: c["score"], reverse=True)
for c in ranked:
    print(f"{c['id']} {c['score']:.2f} {c['text']}")

print("\nbest:", max(chunks, key=lambda c: c["score"])["id"])
print("worst:", min(chunks, key=lambda c: c["score"])["id"])

Multi-level sort and stability

Tuple keys sort by several fields; negate a number to flip direction.

runs = [
    {"model": "b", "score": 0.90, "latency": 300},
    {"model": "a", "score": 0.90, "latency": 120},
    {"model": "c", "score": 0.85, "latency": 100},
]

by_score_then_latency = sorted(runs, key=lambda r: (-r["score"], r["latency"]))
for r in by_score_then_latency:
    print(f"{r['model']}  score={r['score']:.2f}  latency={r['latency']}")

from operator import itemgetter
print("\nitemgetter version:", [r["model"] for r in sorted(runs, key=itemgetter("latency"))])

map, filter, and comprehension side by side

Same result three ways — the comprehension is usually clearest.

scores = [0.91, 0.44, 0.78, 0.62, 0.95]

as_percent_map = list(map(lambda s: round(s * 100), scores))
as_percent_comp = [round(s * 100) for s in scores]

high_filter = list(filter(lambda s: s >= 0.7, scores))
high_comp = [s for s in scores if s >= 0.7]

print("map        :", as_percent_map)
print("comprehension:", as_percent_comp)
print("filter     :", high_filter)
print("comprehension:", high_comp)

print("map with a named function:", list(map(str.upper, ["mlops", "rag"])))

reduce and its better alternatives

Use reduce only when no built-in fits.

import functools
import math

tokens = [120, 340, 88, 502]

print("sum built-in :", sum(tokens))
print("reduce sum   :", functools.reduce(lambda a, b: a + b, tokens))
print("math.prod    :", math.prod([2, 3, 4]))

# A genuine reduce: merge a list of config dicts left to right.
configs = [{"lr": 1e-3}, {"epochs": 3}, {"lr": 2e-5, "fp16": True}]
merged = functools.reduce(lambda acc, d: {**acc, **d}, configs, {})
print("merged config:", merged)

Build a model leaderboard

Try it — in-browser Python

Change the sort key to latency and see the ranking flip.

Output

Python runs in your browser. First run downloads the runtime.

Press Run (or Ctrl+Enter) to execute.

CPython in WebAssembly. Stdlib works. NumPy, pandas, scikit-learn and Matplotlib load on demand, and charts render below. No input(), no GPU, no network installs.

Takeaways

  • lambda holds one expression and belongs inline as a key= argument.
  • sorted(key=lambda r: (-r.score, r.id)) does multi-level sorting; Python's sort is stable.
  • Prefer comprehensions over map/filter; use min/max with key to pick the best record.