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  }