gitee.com/quant1x/num@v0.3.2/rolling.go (about) 1 package num 2 3 // Rolling returns an array with elements that roll beyond the last position are re-introduced at the first. 4 // 滑动窗口, 数据不足是用空数组占位 5 func Rolling[E BaseType](S []E, N any) [][]E { 6 return v2Rolling[E](S, N) 7 } 8 9 // RollingV1 泛型滑动窗口 10 // 11 // 滑动窗口参数N必须是数 12 func RollingV1[E BaseType](S []E, N any, apply func(N DType, values ...E) E) []E { 13 return v3Rolling[E](S, N, apply) 14 } 15 16 // 减少创建block, 增加一个回调函数 17 func v3Rolling[E BaseType](S []E, N any, apply func(N DType, values ...E) E) []E { 18 length := len(S) 19 // 设定窗口 20 var periods Periods 21 switch win := N.(type) { 22 case Window[DType]: 23 periods.Array = win.V 24 periods.N = win.C 25 case Periods: 26 periods = win 27 default: 28 periods = AnyToPeriod(win) 29 } 30 31 array := make([]E, length) 32 defaultValue := TypeDefault[E]() 33 for i := 0; i < length; i++ { 34 n, ok := periods.At(i) 35 if !ok { 36 array[i] = defaultValue 37 continue 38 } 39 shift := int(n) 40 offset := i + 1 41 start := offset - shift 42 end := offset 43 block := S[start:end] 44 result := apply(n, block...) 45 array[i] = result 46 } 47 return array 48 } 49 50 // N 对齐成DType切片 51 func v1Rolling[E BaseType](S []E, N any) [][]E { 52 sLen := len(S) 53 // 这样就具备了序列化滑动窗口的特性了 54 var window []DType 55 switch vn := N.(type) { 56 case int: 57 window = Repeat(DType(vn), sLen) 58 case []int: 59 _N := Slice2DType(vn) 60 window = Align[DType](_N, NaN(), sLen) 61 case []DType: 62 window = Align(vn, NaN(), sLen) 63 case []E: // 这块到不了, N和S不是同一个泛型类型 64 window = Slice2DType(vn) 65 window = Align[DType](window, NaN(), sLen) 66 case DTypeArray: 67 window = vn.DTypes() 68 default: 69 panic(ErrInvalidWindow) 70 } 71 blocks := make([][]E, sLen) 72 for i := 0; i < sLen; i++ { 73 n := window[i] 74 shift := int(n) 75 if DTypeIsNaN(n) || shift > i+1 { 76 blocks[i] = []E{} 77 continue 78 } 79 start := i + 1 - shift 80 end := i + 1 81 subSet := S[start:end] 82 blocks[i] = subSet 83 } 84 return blocks 85 } 86 87 func v2Rolling[E BaseType](S []E, N any) [][]E { 88 sLength := len(S) 89 // 这样就具备了序列化滑动窗口的特性了 90 window := AnyToSlice[DType](N, sLength) 91 blocks := make([][]E, sLength) 92 for i := 0; i < sLength; i++ { 93 n := window[i] 94 shift := int(n) 95 if DTypeIsNaN(n) || shift > i+1 { 96 blocks[i] = []E{} 97 continue 98 } 99 offset := i + 1 100 start := offset - shift 101 end := offset 102 subSet := S[start:end] 103 blocks[i] = subSet 104 } 105 return blocks 106 }