Skip to content
Back to skills

Sorting

ASecurity

Sorting — when to call the built-in, when to roll your own (counting / radix / heap), stability, custom comparators.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added August 31, 2026
ai-agentsjavascriptpythongojavagit

Security analysis

A100/100

Scanned August 31, 2026

npx -y skills add 0bserver07/chimera --skill sorting --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sorting?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Sorting
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/0bserver07-sorting/badge)](https://www.skillsdirectory.com/skills/0bserver07-sorting)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: algo-sorting
description: Sorting — when to call the built-in, when to roll your own (counting / radix / heap), stability, custom comparators.
when-to-use: "Pre-sort for two-pointer / binary-search, top-k via heap, kth-smallest via quickselect, custom-key ordering."
---

## Sorting — `sort()` first, custom rarely

Python's `list.sort` and JavaScript's `Array.prototype.sort` are
both Timsort variants — `O(n log n)` worst case, stable. Reach for
a custom sort *only* when you need a different time/space trade
(counting sort for small integer ranges) or you cannot afford the
copy (heap-based top-k).

### Invariants

* Stable sort: equal-key elements retain their original relative
  order. Both `list.sort()` and recent `Array.prototype.sort` are
  stable; older JS engines were not (pre-2019).
* In-place sort returns `None` in Python (`list.sort`); use
  `sorted()` for a new list. JS `arr.sort()` mutates *and* returns
  the array.
* Sorting by multiple keys: sort by least-significant key first,
  then by next, taking advantage of stability. Or use a tuple key.

### Complexity

* Built-in (Timsort): `O(n log n)` worst, `O(n)` best on
  near-sorted input.
* Quickselect (kth element): `O(n)` average, `O(n^2)` worst.
* Heap-based top-k: `O(n log k)` time, `O(k)` extra space.
* Counting sort: `O(n + r)` for value range `r` — beats comparison
  sort when `r` is small (e.g. 0..255).
* Radix sort: `O(n × d)` for `d` digits — strings of bounded
  length, fixed-precision integers.

### Template — Python (multi-key custom comparator via tuple key)

```python
# Sort by score descending, then by name ascending. Stability is
# implicit: equal-tuple rows keep insertion order.
records.sort(key=lambda r: (-r.score, r.name))

# Stability lets you also chain single-key sorts:
records.sort(key=lambda r: r.name)         # secondary
records.sort(key=lambda r: r.score, reverse=True)  # primary
```

Use a tuple key when you can — it is cleaner and roughly twice as
fast as `functools.cmp_to_key`. Reach for `cmp_to_key` only when
the comparison is non-transitive in tuple form (rare; one classic
case is "biggest-number-by-concatenation").

### Template — Python (heap-based top-k)

```python
import heapq

def top_k_largest(arr: list[int], k: int) -> list[int]:
    """The ``k`` largest elements (in arbitrary order)."""
    if k <= 0: return []
    return heapq.nlargest(k, arr)

def top_k_smallest_by_key(items, k, key):
    return heapq.nsmallest(k, items, key=key)
```

`heapq.nsmallest`/`nlargest` are `O(n log k)` and avoid sorting
the whole list when `k << n`.

### Template — JavaScript (custom comparator, stable since 2019)

```javascript
// Numeric sort — default is lexicographic, which is wrong for numbers.
arr.sort((a, b) => a - b);

// Multi-key: descending score, then ascending name.
records.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name));
```

`localeCompare` is the right tool for human-language strings. For
ASCII identifiers, the `<`/`>` operators are faster.

### Common pitfalls

* **JavaScript default sort is lexicographic.** `[10, 2, 1].sort()`
  gives `[1, 10, 2]`. Always pass a comparator for numbers.
* **Mutating during iteration.** `for i in range(len(arr)): if pred(arr[i]): arr.remove(...)`
  shifts indices and skips elements. Sort first and walk with a
  write index instead.
* **`list.sort()` returns None in Python.** `x = arr.sort()` sets
  `x = None`. Use `sorted(arr)` to get a new list.
* **Comparator returning bool.** JS `sort((a, b) => a > b)` returns
  true/false (1/0 in numeric coercion) — non-transitive, breaks
  stability. Return `a - b` or `cmp(a, b)`.
* **Stability assumed but not provided.** On older runtimes, equal
  keys may shuffle. If correctness depends on it, augment the key
  with the original index.
* **Sort + binary search on objects with mutating fields.** If a
  later edit mutates the sort key, the array is no longer sorted.

### Test corner cases

* Empty array.
* Single-element array.
* Already sorted (best case).
* Reverse sorted (worst case for naive quicksort).
* All-equal values (stability matters here — verify).
* Mixed types (numbers + strings) — coerces and gives surprising
  results. Always sort homogeneous data.
* Floats with NaN — comparisons with NaN return false, leading to
  undefined order. Filter NaNs first.

For "median in a stream", reach for two heaps (min + max). For
"kth smallest", quickselect or `nsmallest` is faster than sort+index.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.