Skip to content

Commit e6c75d9

Browse files
committed
chore: wip
1 parent 113025a commit e6c75d9

File tree

11 files changed

+664
-598
lines changed

11 files changed

+664
-598
lines changed

.stacks/auto-imports.d.ts

Lines changed: 121 additions & 74 deletions
Large diffs are not rendered by default.

.stacks/core/arrays/src/contains.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function contains(needle: string, haystack: string[]) {
2+
return haystack.some(hay => needle.includes(hay))
3+
}
4+
5+
export function containsAll(needles: string[], haystack: string[]) {
6+
return needles.every(needle => contains(needle, haystack))
7+
}
8+
9+
export function containsAny(needles: string[], haystack: string[]) {
10+
return needles.some(needle => contains(needle, haystack))
11+
}
12+
13+
export function containsNone(needles: string[], haystack: string[]) {
14+
return !containsAny(needles, haystack)
15+
}
16+
17+
export function containsOnly(needles: string[], haystack: string[]) {
18+
return containsAll(haystack, needles)
19+
}
20+
21+
export function doesNotContain(needle: string, haystack: string[]) {
22+
return !contains(needle, haystack)
23+
}

.stacks/core/arrays/src/helpers.ts

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
import type { Arrayable, Nullable } from '@stacksjs/types'
2+
import { clamp } from '@stacksjs/utils'
3+
4+
/**
5+
* Convert `Arrayable<T>` to `Array<T>`
6+
*
7+
* @category Array
8+
*/
9+
export function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T> {
10+
array = array ?? []
11+
return Array.isArray(array) ? array : [array]
12+
}
13+
14+
/**
15+
* Convert `Arrayable<T>` to `Array<T>` and flatten it
16+
*
17+
* @category Array
18+
*/
19+
export function flatten<T>(array?: Nullable<Arrayable<T | Array<T>>>): Array<T> {
20+
return toArray(array).flat(1) as Array<T>
21+
}
22+
23+
/**
24+
* Use rest arguments to merge arrays
25+
*
26+
* @category Array
27+
*/
28+
export function mergeArrayable<T>(...args: Nullable<Arrayable<T>>[]): Array<T> {
29+
return args.flatMap(i => toArray(i))
30+
}
31+
32+
export type PartitionFilter<T> = (i: T, idx: number, arr: readonly T[]) => any
33+
34+
/**
35+
* Divide an array into two parts by a filter function
36+
*
37+
* @category Array
38+
* @example const [odd, even] = partition([1, 2, 3, 4], i => i % 2 != 0)
39+
*/
40+
export function partition<T>(array: readonly T[], f1: PartitionFilter<T>): [T[], T[]]
41+
export function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>): [T[], T[], T[]]
42+
export function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>): [T[], T[], T[], T[]]
43+
export function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>): [T[], T[], T[], T[], T[]]
44+
export function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[]]
45+
export function partition<T>(array: readonly T[], f1: PartitionFilter<T>, f2: PartitionFilter<T>, f3: PartitionFilter<T>, f4: PartitionFilter<T>, f5: PartitionFilter<T>, f6: PartitionFilter<T>): [T[], T[], T[], T[], T[], T[], T[]]
46+
export function partition<T>(array: readonly T[], ...filters: PartitionFilter<T>[]): any {
47+
const result: T[][] = new Array(filters.length + 1).fill(null).map(() => [])
48+
49+
array.forEach((e, idx, arr) => {
50+
let i = 0
51+
for (const filter of filters) {
52+
if (filter(e, idx, arr)) {
53+
result[i].push(e)
54+
return
55+
}
56+
i += 1
57+
}
58+
result[i].push(e)
59+
})
60+
return result
61+
}
62+
63+
/**
64+
* Unique an Array
65+
*
66+
* @category Array
67+
*/
68+
export function uniq<T>(array: readonly T[]): T[] {
69+
return Array.from(new Set(array))
70+
}
71+
72+
export function unique<T>(array: readonly T[]): T[] {
73+
return uniq(array)
74+
}
75+
76+
/**
77+
* Unique an Array by a custom equality function
78+
*
79+
* @category Array
80+
*/
81+
export function uniqueBy<T>(array: readonly T[], equalFn: (a: any, b: any) => boolean): T[] {
82+
return array.reduce((acc: T[], cur: any) => {
83+
const index = acc.findIndex((item: any) => equalFn(cur, item))
84+
if (index === -1)
85+
acc.push(cur)
86+
return acc
87+
}, [])
88+
}
89+
90+
/**
91+
* Get last item
92+
*
93+
* @category Array
94+
*/
95+
export function last(array: readonly []): undefined
96+
export function last<T>(array: readonly T[]): T
97+
export function last<T>(array: readonly T[]): T | undefined {
98+
return at(array, -1)
99+
}
100+
101+
/**
102+
* Remove an item from Array
103+
*
104+
* @category Array
105+
*/
106+
export function remove<T>(array: T[], value: T) {
107+
if (!array)
108+
return false
109+
const index = array.indexOf(value)
110+
if (index >= 0) {
111+
array.splice(index, 1)
112+
return true
113+
}
114+
return false
115+
}
116+
117+
/**
118+
* Get nth item of Array. Negative for backward
119+
*
120+
* @category Array
121+
*/
122+
export function at(array: readonly [], index: number): undefined
123+
export function at<T>(array: readonly T[], index: number): T
124+
export function at<T>(array: readonly T[] | [], index: number): T | undefined {
125+
const len = array.length
126+
if (!len)
127+
return undefined
128+
129+
if (index < 0)
130+
index += len
131+
132+
return array[index]
133+
}
134+
135+
/**
136+
* Generate a range array of numbers. The `stop` is exclusive.
137+
*
138+
* @category Array
139+
*/
140+
export function range(stop: number): number[]
141+
export function range(start: number, stop: number, step?: number): number[]
142+
export function range(...args: any): number[] {
143+
let start: number, stop: number, step: number
144+
145+
if (args.length === 1) {
146+
start = 0
147+
step = 1;
148+
([stop] = args)
149+
}
150+
else {
151+
([start, stop, step = 1] = args)
152+
}
153+
154+
const arr: number[] = []
155+
let current = start
156+
while (current < stop) {
157+
arr.push(current)
158+
current += step || 1
159+
}
160+
161+
return arr
162+
}
163+
164+
/**
165+
* Move element in an Array
166+
*
167+
* @category Array
168+
* @param arr
169+
* @param from
170+
* @param to
171+
*/
172+
export function move<T>(arr: T[], from: number, to: number) {
173+
arr.splice(to, 0, arr.splice(from, 1)[0])
174+
return arr
175+
}
176+
177+
/**
178+
* Clamp a number to the index range of an array.
179+
*
180+
* @category Array
181+
*/
182+
export function clampArrayRange(arr: readonly unknown[], n: number) {
183+
return clamp(n, 0, arr.length - 1)
184+
}
185+
186+
/**
187+
* Get random items from an array
188+
*
189+
* @category Array
190+
*/
191+
export function sample<T>(arr: T[], count: number) {
192+
return Array.from({ length: count }, _ => arr[Math.round(Math.random() * (arr.length - 1))])
193+
}
194+
195+
/**
196+
* Shuffle an array. This function mutates the array.
197+
*
198+
* @category Array
199+
*/
200+
export function shuffle<T>(array: T[]): T[] {
201+
for (let i = array.length - 1; i > 0; i--) {
202+
const j = Math.floor(Math.random() * (i + 1));
203+
[array[i], array[j]] = [array[j], array[i]]
204+
}
205+
return array
206+
}

0 commit comments

Comments
 (0)