Skip to content

Commit

Permalink
feat: add Array.window (#4477)
Browse files Browse the repository at this point in the history
  • Loading branch information
f15u authored and effect-bot committed Mar 3, 2025
1 parent 519cf79 commit e3284ed
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/tender-kangaroos-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

Add `Array.window` function
12 changes: 12 additions & 0 deletions packages/effect/dtslint/Array.tst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,18 @@ describe("Array", () => {
.type.toBe<[[string, ...Array<string>], ...Array<[string, ...Array<string>]>]>()
})

it("window", () => {
// Array
expect(Array.window(strings, 2)).type.toBe<Array<Array<string>>>()
expect(pipe(strings, Array.window(2))).type.toBe<Array<Array<string>>>()
expect(Array.window(2)(strings)).type.toBe<Array<Array<string>>>()

// NonEmptyArray
expect(Array.window(nonEmptyStrings, 2)).type.toBe<Array<Array<string>>>()
expect(pipe(nonEmptyStrings, Array.window(2))).type.toBe<Array<Array<string>>>()
expect(Array.window(2)(nonEmptyStrings)).type.toBe<Array<Array<string>>>()
})

it("reverse", () => {
// Array
expect(Array.reverse(strings)).type.toBe<Array<string>>()
Expand Down
31 changes: 31 additions & 0 deletions packages/effect/src/Array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,37 @@ export const chunksOf: {
return []
})

/**
* Creates sliding windows of size `n` from an `Iterable`.
* If the number of elements is less than `n` or if `n` is not greater than zero,
* an empty array is returned.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* assert.deepStrictEqual(Array.window(numbers, 3), [[1, 2, 3], [2, 3, 4], [3, 4, 5]])
* assert.deepStrictEqual(Array.window(numbers, 6), [])
* ```
*
* @category splitting
* @since 3.13.2
*/
export const window: {
(n: number): <A>(self: Iterable<A>) => Array<Array<A>>
<A>(self: Iterable<A>, n: number): Array<Array<A>>
} = dual(2, <A>(self: Iterable<A>, n: number): Array<Array<A>> => {
const input = fromIterable(self)
if (n > 0 && isNonEmptyReadonlyArray(input)) {
return Array.from(
{ length: input.length - (n - 1) },
(_, index) => input.slice(index, index + n)
)
}
return []
})

/**
* Group equal, consecutive elements of a `NonEmptyReadonlyArray` into `NonEmptyArray`s using the provided `isEquivalent` function.
*
Expand Down
12 changes: 12 additions & 0 deletions packages/effect/test/Array.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,18 @@ describe("Array", () => {
assertSingleChunk(Arr.make(1, 2), 3)
})

it("window", () => {
deepStrictEqual(Arr.window(2)([]), [])

deepStrictEqual(Arr.window(2)([1, 2, 3, 4, 5]), [[1, 2], [2, 3], [3, 4], [4, 5]])
deepStrictEqual(Arr.window(3)([1, 2, 3, 4, 5]), [[1, 2, 3], [2, 3, 4], [3, 4, 5]])

// n out of bounds
deepStrictEqual(Arr.window([1, 2, 3, 4, 5], 6), [])
deepStrictEqual(Arr.window([1, 2, 3, 4, 5], 0), [])
deepStrictEqual(Arr.window([1, 2, 3, 4, 5], -1), [])
})

it("min", () => {
deepStrictEqual(Arr.min(Num.Order)([2, 1, 3]), 1)
deepStrictEqual(Arr.min(Num.Order)([3]), 3)
Expand Down

0 comments on commit e3284ed

Please sign in to comment.