Skip to content

Commit 6b38995

Browse files
committed
Add Array::windows
1 parent 36ee646 commit 6b38995

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

builtin/array.mbt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,47 @@ pub fn Array::chunk_by[T](
16391639
chunks
16401640
}
16411641
1642+
///|
1643+
/// Generates consecutive overlapping subarrays of the specified window size.
1644+
///
1645+
/// Parameters:
1646+
///
1647+
/// * `array` : The array to be processed with sliding windows.
1648+
/// * `size` : The window length. Must be a positive integer.
1649+
///
1650+
/// Returns an array of subarrays, where each subarray contains size consecutive elements
1651+
/// starting from successive positions. Consecutive windows overlap by all but one element.
1652+
/// If the input array's length is less than the window size, no valid windows are produced
1653+
/// and the result is an empty array.
1654+
///
1655+
/// Example:
1656+
///
1657+
/// ```moonbit
1658+
/// test "windows" {
1659+
/// let arr = [1, 2, 3, 4, 5]
1660+
/// let windows = arr.windows(2)
1661+
/// inspect!(windows, content="[[1, 2], [2, 3], [3, 4], [4, 5]]")
1662+
/// }
1663+
///
1664+
/// test "empty_windows" {
1665+
/// let arr : Array[Int] = [1, 2]
1666+
/// inspect!(arr.windows(3), content="[]")
1667+
/// }
1668+
/// ```
1669+
pub fn Array::windows[T](self : Array[T], size : Int) -> Array[Array[T]] {
1670+
let capacity = self.length() - size + 1
1671+
if capacity < 1 {
1672+
return []
1673+
}
1674+
let windows = Array::new(capacity~)
1675+
for i in 0..<capacity {
1676+
let window = Array::make_uninit(size)
1677+
Array::unsafe_blit(window, 0, self, i, size)
1678+
windows.push(window)
1679+
}
1680+
windows
1681+
}
1682+
16421683
///|
16431684
/// Splits an array into chunks using a predicate function. Creates chunks by
16441685
/// grouping consecutive elements that do not satisfy the predicate function.

builtin/array_test.mbt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,18 @@ test "chunks_by" {
494494
)
495495
}
496496

497+
///|
498+
test "array_windows" {
499+
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
500+
let windows = arr.windows(11)
501+
assert_eq!(windows.length(), 0)
502+
let windows = arr.windows(7)
503+
assert_eq!(windows.length(), 3)
504+
inspect!(windows[0], content="[1, 2, 3, 4, 5, 6, 7]")
505+
inspect!(windows[1], content="[2, 3, 4, 5, 6, 7, 8]")
506+
inspect!(windows[2], content="[3, 4, 5, 6, 7, 8, 9]")
507+
}
508+
497509
///|
498510
test "array_get_out_of_bounds" {
499511
let arr = [1, 2, 3]

builtin/builtin.mbti

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ impl Array {
124124
unsafe_blit_fixed[A](Self[A], Int, FixedArray[A], Int, Int) -> Unit
125125
unsafe_get[T](Self[T], Int) -> T
126126
unsafe_pop[T](Self[T]) -> T
127+
windows[T](Self[T], Int) -> Self[Self[T]]
127128
}
128129
impl[T] Add for Array[T]
129130
impl[T : Compare] Compare for Array[T]

0 commit comments

Comments
 (0)