-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprocess.go
108 lines (98 loc) · 2.99 KB
/
process.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
// Tideland Go Slices
//
// Copyright (C) 2022-2023 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
package slices // import "tideland.dev/go/slices"
//--------------------
// COMPUTATIONS
//--------------------
// FoldL iterates over the slice from left to right. It calls fun() for
// each value passing the initial accumulator. The accumulator returned
// by each function call is used as input at the next call. The last one will
// be returned.
func FoldL[V, Acc any](vs []V, acc Acc, fun func(V, Acc) Acc) Acc {
for _, v := range vs {
acc = fun(v, acc)
}
return acc
}
// FoldLFirst iterates over the slice from left to right. It calls fun() for
// each value passing the first value as accumulator. The accumulator returned
// by each function call is used as input at the next call. The last one will be
// returned.
func FoldLFirst[V any](vs []V, fun func(V, V) V) V {
var first V
if len(vs) == 0 {
// Return default value.
return first
}
first = vs[0]
return FoldL(vs[1:], first, fun)
}
// FoldR iterates over the slice from right to left. It calls fun() for
// each value passing the initial accumulator. The accumulator returned
// by each function call is used as input at the next call. The last one will be
// returned.
func FoldR[V, Acc any](vs []V, acc Acc, fun func(V, Acc) Acc) Acc {
for i := len(vs) - 1; i >= 0; i-- {
acc = fun(vs[i], acc)
}
return acc
}
// FoldRLast iterates over the slice from right to left. It calls fun() for
// each value passing the last value as accumulator. The accumulator returned
// by each function call is used as input at the next call. The last one will be
// returned.
func FoldRLast[V any](vs []V, fun func(V, V) V) V {
var last V
if len(vs) == 0 {
// Return default value.
return last
}
last = vs[len(vs)-1]
return FoldR(vs[:len(vs)-1], last, fun)
}
// MapFoldL combines the operations of Map() and FoldL() in one pass.
func MapFoldL[I, O, Acc any](ivs []I, acc Acc, fun func(I, Acc) (O, Acc)) ([]O, Acc) {
var ov O
var ovs []O
if ivs != nil {
ovs = make([]O, len(ivs))
}
for i, iv := range ivs {
ov, acc = fun(iv, acc)
ovs[i] = ov
}
return ovs, acc
}
// MapFoldR combines the operations of Map() and FoldR() in one pass.
func MapFoldR[I, O, Acc any](ivs []I, acc Acc, fun func(I, Acc) (O, Acc)) ([]O, Acc) {
var ov O
var ovs []O
if ivs != nil {
ovs = make([]O, len(ivs))
}
for i := len(ivs) - 1; i >= 0; i-- {
ov, acc = fun(ivs[i], acc)
ovs[i] = ov
}
return ovs, acc
}
// Partition checks all values of the slices and returns all where pred() returns
// true in one slice and false in another one. Their individual ordering will be
// the same of the original one.
func Partition[V any](vs []V, pred func(V) bool) ([]V, []V) {
var satisfying []V
var notSatisfying []V
for _, v := range vs {
if pred(v) {
satisfying = append(satisfying, v)
} else {
notSatisfying = append(notSatisfying, v)
}
}
return satisfying, notSatisfying
}
// EOF