Vectorized operations vs loops
Always prefer vectorized operations over JavaScript loops. numpy-ts operations run on typed arrays with optimized internal loops, avoiding the overhead of JavaScript function calls and dynamic type checks.
Common loop-to-vectorized translations
| Loop pattern | Vectorized equivalent |
|---|
for (i) result[i] = a[i] + b[i] | np.add(a, b) |
for (i) result[i] = a[i] > threshold ? 1 : 0 | np.greater(a, threshold) |
for (i) sum += a[i] | np.sum(a) |
for (i) result[i] = Math.max(a[i], 0) | np.maximum(a, 0) |
for (i) if (mask[i]) result.push(a[i]) | np.extract(mask, a) |
for (i) result[i] = condition ? x[i] : y[i] | np.where(condition, x, y) |
Avoiding unnecessary copies (use views when possible)
Views share the same underlying data buffer as the original array. Operations that return views are effectively free — no memory allocation and no data copying.
Check whether an operation returned a view
Views share data. Modifying a view changes the original array. If you need an independent copy, use np.copy() or .copy().
Dtype selection for memory efficiency
Choose the smallest dtype that can represent your data. This reduces memory usage and can improve cache performance.
Dtype selection guide
| Data type | Bytes | Use when |
|---|
float64 | 8 | Maximum precision needed, scientific computation |
float32 | 4 | ML inference, graphics, when 7 digits of precision suffice |
int32 | 4 | Integer data up to ~2 billion |
int16 | 2 | Audio samples, small integer ranges |
int8 / uint8 | 1 | Pixel values, boolean-like data, lookup indices |
bool | 1 | Masks and boolean arrays |
Use .astype() to convert between dtypes. Going from a wider type to a narrower one truncates (float to int) or wraps (large int to small int).
Using keepdims for broadcasting
When reducing along an axis, the reduced dimension disappears by default. Use keepdims: true to preserve it as a size-1 dimension, which makes subsequent broadcasting operations work without manual reshaping.