| name | stacks-arrays |
| description | Use when working with array utilities in Stacks — statistical operations (average, median, mode, standard deviation, z-score, percentile, covariance), array manipulation (unique, flatten, partition, shuffle, sample, move), containment checks, or the Arr facade. Covers @stacksjs/arrays. |
| license | MIT |
| compatibility | Bun >= 1.3.0, TypeScript |
| allowed-tools | Read Edit Write Bash Grep Glob |
Stacks Array Utilities
Key Paths
- Core package:
storage/framework/core/arrays/src/
- Package:
@stacksjs/arrays
Architecture
The index.ts exports:
export * from './arr'
export * as arr from './arr'
export * from './macro'
The arr.ts re-exports from three submodules:
contains.ts — containment check functions
helpers.ts — array manipulation (toArray, flatten, partition, unique, shuffle, etc.)
math.ts — statistical functions (average, median, mode, variance, etc.)
The macro.ts provides the Arr and arr facade objects.
Array Manipulation (helpers.ts)
Converting to Arrays
import type { Arrayable, Nullable } from '@stacksjs/types'
toArray('foo')
toArray(['foo'])
toArray(null)
toArray(undefined)
toArray(1)
toArray({ a: 1 })
Flattening
flatten([1, [2, [3, [4, [5]]]]])
flatten(null)
flatten('hello')
Merging
mergeArrayable([1, 2], [3, 4], [5, 6])
mergeArrayable(1, [2, 3], null)
Unique Values
uniq([1, 1, 2, 3])
unique([1, 1, 2, 3])
uniqueBy(
[{ id: 1 }, { id: 1 }, { id: 2 }],
(a, b) => a.id === b.id
)
Accessing Elements
last([1, 2, 3])
last([])
at([1, 2, 3], 0)
at([1, 2, 3], -1)
at([1, 2, 3], 3)
at([], 0)
Mutation
const arr = [1, 2, 3]
remove(arr, 2)
remove(arr, 4)
Reordering
move([1, 2, 3, 4], 0, 2)
move([1, 2, 3, 4], 0, -1)
move([1, 2, 3, 4], -1, 0)
Random Selection
sample([1, 2, 3, 4, 5], 3)
Shuffling
shuffle([1, 2, 3, 4])
Clamping
clampArrayRange([1, 2, 3], 0)
clampArrayRange([1, 2, 3], 5)
clampArrayRange([1, 2, 3], -1)
Partitioning
const [odds, evens] = partition([1, 2, 3, 4], i => i % 2 !== 0)
const [small, medium, large] = partition(
[1, 5, 10, 50, 100],
n => n < 10,
n => n < 50
)
Partition filter signature: (item: T, index: number, array: readonly T[]) => any
Containment Checks (contains.ts)
All containment functions work with string[]. The contains function checks if the needle includes any element from the haystack (substring matching via needle.includes(hay)).
contains('foobar', ['foo', 'baz'])
contains('hello', ['foo', 'bar'])
containsAll(['foo', 'bar'], ['foobar', 'barx'])
containsAll(['foo', 'qux'], ['foobar'])
containsAny(['foo', 'qux'], ['foobar'])
containsAny(['baz', 'qux'], ['foobar'])
containsNone(['baz', 'qux'], ['foobar'])
containsNone(['foo', 'qux'], ['foobar'])
containsOnly(['foo', 'bar'], ['foobar', 'barx'])
doesNotContain(, [, ])
(, [])
Important: contains uses needle.includes(hay), NOT haystack.includes(needle). It checks if the needle string contains any of the haystack substrings. This is substring matching, not array membership.
Statistical Functions (math.ts)
All statistical functions expect number[] and throw Error on empty arrays (except sum and product which return identity values).
Basic Aggregates
sum([1, 2, 3, 4])
product([2, 3, 4])
min([5, 1, 3])
max([5, 1, 3])
range([1, 5, 3])
Central Tendency
average([1, 2, 3, 4, 5])
avg([1, 2, 3])
median([1, 2, 3, 4, 5])
median([1, 2, 3, 4])
mode([1, 2, 2, 3, 3, 4, 4, 4])
mode([1, 2, 3, 4])
Dispersion
variance([1, 2, 3, 4])
standardDeviation([1, 2, 3, 4])
Advanced Statistics
zScore([1, 2, 3, 4], 2)
zScore([1, 2, 3, 4], 3)
percentile([1, 2, 3, 4, 5], 50)
percentile([1, 2, 3, 4], 25)
interquartileRange([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
covariance([1, 2, 3, 4], [1, 2, 3, 4])
covariance([, , , ], [, , , ])
Important: variance and standardDeviation compute POPULATION metrics (divides by N), not sample metrics (which would divide by N-1).
Arr Facade (macro.ts)
Both Arr and arr are exported as equivalent facade objects.
import { Arr, arr } from '@stacksjs/arrays'
Arr.toArray(value)
Arr.flatten(array)
Arr.mergeArrayable(...arrays)
Arr.unique(arr)
Arr.uniqueBy(arr, equalFn)
Arr.last(arr)
Arr.at(arr, index)
Arr.remove(arr, value)
Arr.move(arr, from, to)
Arr.clampArrayRange(arr, n)
Arr.shuffle(arr)
Arr.sample(arr, count)
Arr.random(arr, count)
.(arr, filter)
.(needle, haystack)
.(needles, haystack)
.(needles, haystack)
.(needles, haystack)
.(needles, haystack)
.(needle, haystack)
.(arr)
.(arr)
.(arr)
.(arr)
.(arr)
.(arr)
Note: The Arr facade does NOT expose variance, standardDeviation, zScore, percentile, interquartileRange, covariance, product, min, or max -- use the standalone functions for those.
The facade adds one extra method not in the standalone functions:
Arr.random(arr, count)
Exported Types
type PartitionFilter<T> = (item: T, index: number, array: readonly T[]) => any
Gotchas
shuffle() and move() MUTATE the original array -- they do NOT return copies
remove() MUTATES the original array and returns a boolean (not the removed element)
sample() can return duplicate items since each pick is independent
contains() uses SUBSTRING matching (needle.includes(hay)), not array membership -- contains('foobar', ['foo']) is true
- Statistical functions throw on empty arrays (except
sum which returns 0 and product which returns 1)
variance and standardDeviation use POPULATION formulas (divide by N), not sample formulas
percentile takes a value 0-100 and uses linear interpolation between sorted array elements
interquartileRange splits the sorted array at the midpoint and takes median of each half
mode returns the first most-frequent value when there's a tie
- For complex collection operations with chaining, consider
@stacksjs/collections
- The
Arr facade wraps most but not all standalone functions -- advanced stats need direct imports