-
Notifications
You must be signed in to change notification settings - Fork 4
/
array.ts
189 lines (173 loc) · 4.29 KB
/
array.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/**
* Get array element type
*
* @typeParam T - Array type
* @example ```ts
* ElementType<number[]> // number
* ElementType<Array<string>> // string
* ```
*/
export type ElementType<T extends Array<any>> = T extends Array<infer R> ? R : never
/**
* Ensure value is a array
*
* @param value - array or a element of array
* @returns array
* @example ```ts
* ensure_array(42) // [42]
* ensure_array([]) // []
* ```
*/
export function ensure_array<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [ value ]
}
/**
* Test value is array, just wrap `Array.isArray`
*
* @param value - test value
* @returns test result
* @example ```ts
* is_array([]) // true
* is_array(Array()) // true
* is_array({ 0: 42 }) // false
* ```
*/
export function is_array(value: any): boolean {
return Array.isArray(value)
}
/**
* Test a array have empty element
*
* @typeParam T - array type
* @param array - array
* @returns test result
* @example ```ts
* is_empty_array([]) // true
* is_empty_array(Array()) // true
* ```
*/
export function is_empty_array<T>(array: Array<T>): boolean {
return 0 === array.length
}
/**
* Select some elements from array
*
* @param array - array
* @param options - choose options
* @returns choosed array
*/
export function select_array<T>(array: T[], options: SelectArrayOptions<T> = {}): T[] {
const {
include = [],
exclude = [],
test = Object.is
} = options
const inc = ensure_array(include)
const exc = ensure_array(exclude)
return array
.concat(inc)
.filter(item => !exc.some(e => test(e, item)))
}
/**
* Options of choose_array
*
* @typeParam T - array element type
*/
export interface SelectArrayOptions<T> {
readonly include?: T | T[],
readonly exclude?: T | T[],
readonly test?: (a: T, b: T) => boolean
}
//#region split_array
/**
* cut list by index
*
* @param list - list
* @param index - list index
* @returns splited list
* @example ```ts
* cut_at([1,2,3], 1) // [[1,2], [3]]
* ```
*/
export function cut_at(string: string, index: number): [ string, string ]
export function cut_at<T>(list: T[], index: number): [ T[], T[] ]
export function cut_at(list: any, index: number): any {
if(index < 0) {
return [ list.slice(0, index), list.slice(index) ]
}
else {
const pos = index + 1
return [ list.slice(0, pos), list.slice(pos) ]
}
}
/**
* cut list by size
*
* @param list - list
* @param size - size
* @returns splited list
* @throws size < 0
* @example ```ts
* split([]) // [[]]
* split([1,2,3], 2) // [[1,2], [3]]
* ```
*/
export function cut(string: string, size: number): [ string, string ]
export function cut<T>(list: T[], size: number): [ T[], T[] ]
export function cut(list: any, size: number): any {
if(size < 0) throw new Error(`expected size >= 0, got "${size}"`)
return [ list.slice(0, size), list.slice(size) ]
}
/**
* cut list per size
*
* @param list - list
* @param size - size
* @returns splited list
* @example ```ts
* cut_all([1,2,3,4,5,6], 2) // [[1,2], [3,4], [5,6]]
* cut_all([1,2,3,4,5,6], 1, 2) // [[1], [2,3], [4], [5,6]]
* ```
*/
export function cut_all(string: string, ...size: number[]): string[]
export function cut_all<T>(list: T[], ...size: number[]): T[][]
export function cut_all(list: any, ...size: number[]): any {
switch(size.length) {
case 0: return [list]
case 1: return cut_1(list, size[0])
default: return cut_n(list, size)
}
function cut_1<T>(list: T[], size: number): T[][] {
if(size < 0) throw new Error(`expected size >= 0, got "${size}"`)
const arr: T[][] = []
const len = list.length
let i = 0
while(i < len) {
const beg = i, end = i + size
arr.push(list.slice(beg, end))
i = end
}
return arr
}
function cut_n<T>(list: T[], sizes: number[]): T[][] {
const arr: T[][] = []
const len = list.length
let i = 0, j = 0
while(i < len) {
const size = sizes[j]
if(size < 0) throw new Error(`expected size[${j}] >= 0, got "${size}"`)
const beg = i, end = i + size
arr.push(list.slice(beg, end))
i = end
j = next(j)
}
return arr
function next(index: number) {
switch(index) {
case size.length - 1: return 0
default: return index + 1
}
}
}
}
//#endregion