-
Notifications
You must be signed in to change notification settings - Fork 0
/
reduce.go
156 lines (136 loc) · 4.16 KB
/
reduce.go
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
package slice
import (
"fmt"
compare_anything "github.com/golang-infrastructure/go-compare-anything"
"github.com/golang-infrastructure/go-gtypes"
"strings"
)
// ---------------------------------------------------------------------------------------------------------------------
//type ReduceFunc[T, R any] func(index int, item T, result R) R
// Reduce 把切片中的所有元素合并为一个
func Reduce[T, R any](slice []T, initResult R, reduceFunc func(index int, item T, result R) R) R {
result := initResult
for index, item := range slice {
result = reduceFunc(index, item, result)
}
return result
}
// ReduceByKey 根据key把切片中的元素分组并合并返回
func ReduceByKey[T any, K comparable, R any](slice []T, keyFunc func(index int, item T) K, reduceFunc func(index int, item T, result R) R) map[K]R {
keyMap := make(map[K]R, 0)
for index, item := range slice {
key := keyFunc(index, item)
result := reduceFunc(index, item, keyMap[key])
keyMap[key] = result
}
return keyMap
}
// ---------------------------------------------------------------------------------------------------------------------
// Max 求切片中的最大值
func Max[T gtypes.Ordered](slice []T) T {
if len(slice) == 0 {
var zero T
return zero
}
max := slice[0]
for i := 1; i < len(slice); i++ {
if slice[i] > max {
max = slice[i]
}
}
return max
}
// MaxByComparator 求出切片中的最大值,使用给定的比较器来比较元素之间的大小
func MaxByComparator[T any](slice []T, comparator compare_anything.Comparator[T]) T {
if len(slice) == 0 {
var zero T
return zero
}
return Reduce(slice[1:], slice[0], func(index int, item T, result T) T {
if comparator(item, result) > 0 {
return item
} else {
return result
}
})
}
// ---------------------------------------------------------------------------------------------------------------------
// Min 求切片中的最小值
func Min[T gtypes.Ordered](slice []T) T {
if len(slice) == 0 {
var zero T
return zero
}
min := slice[0]
for i := 1; i < len(slice); i++ {
if slice[i] < min {
min = slice[i]
}
}
return min
}
// MinByComparator 求出切片中的最小值,使用给定的比较器来比较元素之间的大小
func MinByComparator[T any](slice []T, comparator compare_anything.Comparator[T]) T {
if len(slice) == 0 {
var zero T
return zero
}
return Reduce(slice[1:], slice[0], func(index int, item T, result T) T {
if comparator(item, result) < 0 {
return item
} else {
return result
}
})
}
// ------------------------------------------------ ---------------------------------------------------------------------
// TODO 2022-10-24 03:03:24 有点难搞下面这几个,可能要引入新的概念
//// Avg 注意,有溢出风险
//func Avg[T Float](slice []T) T {
// if len(slice) == 0 {
// return 0
// }
// var sum T
// for _, item := range slice {
// sum += item
// }
// return sum * 1.0 / len(slice)
//}
//
//// AvgByValueFunc 注意,有溢出风险
//func AvgByValueFunc[T any, V Integer | Float](slice []T, valueFunc func(index int, item T) V) V {
// var sum V
// for index, item := range slice {
// sum += valueFunc(index, item)
// }
// return sum
//}
// ------------------------------------------------ ---------------------------------------------------------------------
// Sum 注意,有溢出风险
func Sum[T gtypes.Integer | gtypes.Float](slice []T) T {
var sum T
for _, item := range slice {
sum += item
}
return sum
}
// SumByValueFunc 注意,有溢出风险
func SumByValueFunc[T any, V gtypes.Integer | gtypes.Float](slice []T, valueFunc func(index int, item T) V) V {
var sum V
for index, item := range slice {
sum += valueFunc(index, item)
}
return sum
}
// ------------------------------------------------ ---------------------------------------------------------------------
func Join[T any](slice []T, delimiter string) string {
sb := strings.Builder{}
for index, item := range slice {
sb.WriteString(fmt.Sprintf("%v", item))
if index != len(slice)-1 {
sb.WriteString(delimiter)
}
}
return sb.String()
}
// ------------------------------------------------ ---------------------------------------------------------------------