Array Compaction
Remove elements in-place based on a predicate while preserving the remaining elements.
Array Compaction
Array compaction removes elements that do not satisfy a predicate by overwriting them with elements that do. It operates in-place and preserves the relative order of retained elements.
You use it when filtering data without allocating additional memory.
Problem
Given an array $A$ of length $n$ and a predicate $P(x)$, remove all elements that do not satisfy $P$, and return the new length.
After compaction:
- for all $i < k$, $P(A[i])$ holds
- indices $i \ge k$ are ignored
Algorithm
Use a write pointer to overwrite unwanted elements.
compact(A, P):
k = 0
for i from 0 to length(A) - 1:
if P(A[i]):
A[k] = A[i]
k += 1
return k
Example
Let
$$ A = [8, 3, 5, 2, 1, 4] $$
Keep even numbers:
$$ P(x): x \bmod 2 = 0 $$
| step | i | value | action | array | k |
|---|---|---|---|---|---|
| 1 | 0 | 8 | keep | [8, 3, 5, 2, 1, 4] | 1 |
| 2 | 1 | 3 | skip | [8, 3, 5, 2, 1, 4] | 1 |
| 3 | 2 | 5 | skip | [8, 3, 5, 2, 1, 4] | 1 |
| 4 | 3 | 2 | keep | [8, 2, 5, 2, 1, 4] | 2 |
| 5 | 4 | 1 | skip | [8, 2, 5, 2, 1, 4] | 2 |
| 6 | 5 | 4 | keep | [8, 2, 4, 2, 1, 4] | 3 |
Result:
$$ [8, 2, 4] $$
New length:
$$ k = 3 $$
Correctness
At each step:
- indices $[0, k-1]$ contain elements that satisfy $P$ in their original order
- indices $[k, i]$ may contain unprocessed or discarded elements
When $P(A[i])$ holds, writing it to position $k$ extends the valid prefix. Since elements are processed left to right, their order is preserved.
After the loop, the first $k$ elements form exactly the filtered array.
Complexity
| operation | time |
|---|---|
| compaction | $O(n)$ |
Space usage:
$$ O(1) $$
When to Use
Array compaction is appropriate when:
- elements must be filtered in-place
- order must be preserved
- memory allocation should be avoided
- output size is smaller than input
It is less suitable when:
- original array must remain unchanged
- removed elements must be preserved elsewhere
Implementation
def compact(a, predicate):
k = 0
for i in range(len(a)):
if predicate(a[i]):
a[k] = a[i]
k += 1
return k
func Compact[T any](a []T, pred func(T) bool) int {
k := 0
for i := 0; i < len(a); i++ {
if pred(a[i]) {
a[k] = a[i]
k++
}
}
return k
}