-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy patharray.ts
More file actions
116 lines (105 loc) · 2.86 KB
/
array.ts
File metadata and controls
116 lines (105 loc) · 2.86 KB
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
/**
* Copyright (c) 2022 Hengyang Zhang
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
/**
* Group by
*
* @param arr original array
* @param keyFunc key generator
* @returns grouped map
* @since 1.0.0
*/
export function groupBy<T, R>(
arr: T[],
keyFunc: (e: T, idx: number) => string | number | undefined | null,
downstream: (grouped: T[], key: string) => R
): Record<string, R> {
const groupedMap: { [key: string]: T[] } = {}
arr.forEach((e, i) => {
const key = keyFunc(e, i)
if (key === undefined || key === null) {
return
}
const existArr: T[] = groupedMap[key] || []
existArr.push(e)
groupedMap[key] = existArr
})
const result: Record<string, R> = {}
Object.entries(groupedMap)
.forEach(([key, grouped]) => result[key] = downstream(grouped, key))
return result
}
/**
* Rotate the array without new one returned
*
* @param arr the targe array
* @param count count to rotate, must be positive, or 1 is default
* @param rightOrLeft rotate right or left, true means left, false means right, default is false
*/
export function rotate<T>(arr: T[], count?: number, rightOrLeft?: boolean): void {
let realTime = 1
if (count && count > 1) {
realTime = count
}
const operation = !!rightOrLeft
// Right
? (a: T[]) => {
const first = a.pop()
first && a.unshift(first)
}
// Left
: (a: T[]) => {
const last = a.shift()
last && a.push(last)
}
for (; realTime > 0; realTime--) {
operation(arr)
}
}
/**
* Summarize
*
* @param arr target arr
*/
export function sum(arr: number[]): number {
return arr?.reduce?.((a, b) => (a ?? 0) + (b ?? 0), 0) ?? 0
}
/**
* @since 2.1.0
* @returns null if arr is empty or null
*/
export function average(arr: number[]): number | null {
if (!arr?.length) return null
return sum(arr) / arr.length
}
export function allMatch<T>(arr: T[], predicate: (t: T) => boolean): boolean {
return !arr?.filter?.(e => !predicate?.(e))?.length
}
export function anyMatch<T>(arr: T[], predicate: (t: T) => boolean): boolean {
return !!arr?.filter?.(e => predicate?.(e))?.length
}
export function range(len: number): number[] {
const arr: number[] = []
for (let i = 0; i < len; i++) {
arr.push(i)
}
return arr
}
export function containsAny<T>(arr1: T[], arr2: T[]): boolean {
if (!arr1?.length || !arr2?.length) return false
return !!arr1.find(e => arr2.includes(e))
}
export function joinAny<T = any>(arr: T[], separator: T): T[] {
if (!arr.length) return [separator]
return arr.reduce<T[]>(
(arr, e) => {
arr.length && arr.push(separator)
arr.push(e)
return arr
},
[],
)
}