返回数组的有效长度
numeric  getrealsize(array<Numeric> arr)
    {
        Numeric i;
        numeric result;
        for i = 0 to GetArraySize(arr)-1
        {
            If(arr[i]<>0) result = i;
        }
        return result;
    }

有效长度定义类似小数的有效位数,按数组最后一个非0元素的位置作为数组的有效长度。

函数如何返回多个数组
数组的声明
关于Summation函数麻烦老师解答:当回溯的K线长度不够的时候,返回的值是以什么规律取值
自定义指数数据长度设置
数组
关于策略有效性的请教
如何修改策略运行的有效期?
序列值和数组的区别
a函数对大商所的套利合约是否有效?
关于用户函数返回值类型的疑问

其实设计成为 arr[0]存放count更简单,还不需要遍历。然后设计一个enqueue和delete函数 维护count即可。

如果涉及到大量的删除和enqueue,可以考虑使用环形结构,扩大表头,存放表头大小,front和tear指针,不需要频繁进行内存拷贝。

可以给出实例🤝

// =============================================================================

// 基础队列模块(BQue)设计文档

// 版本:3.1(增强版)

// =============================================================================


// =============================================================================

// 第一部分:模块概述

// =============================================================================


// 基础队列模块提供灵活的队列操作功能,在标准FIFO基础上增加条件删除等操作。

// 每个子项包含多个字段,支持结构化数据存储和条件筛选。



// =============================================================================

// 第二部分:数据结构定义

// =============================================================================


// 【基础队列】一维数组模拟二维表格结构设计

// 二维结构定义:

// - 行:代表队列的“行维度”,分为【表头行】和【子项行】

// - 列:代表每行的“字段维度”,表头行/子项行均包含多个字段列

// 一维数组与二维行列的映射:数组索引 = 行偏移 + 列偏移(按“行优先”顺序存储)


// 【表头行(第0行)】

// - 表头行总列数 HeaderSize = max(2, FieldSize) (最小占2列,保证基础元数据存储)

//   表头行列定义:

//   - 第0行第0列:存储队列当前有效子项个数(核心元数据)

//   - 第0行第1列:存储单个子项行的字段列数(FieldSize)

//   - 第0行第2~HeaderSize-1列:预留扩展列,暂未使用


// 【子项行(从第1行开始)】

// - 子项行起始行号:1(表头行的下一行)

// - 单个子项行占用列数:FieldSize

// - 队列子项访问规则(二维行列 → 一维数组索引):

//   第N个子项行的第1列 → 一维数组索引 = HeaderSize + (N - 1) * FieldSize + 0

//   第N个子项行的第2列 → 一维数组索引 = HeaderSize + (N - 1) * FieldSize + 1

//   第N个子项行的第M列 → 一维数组索引 = HeaderSize + (N - 1) * FieldSize + (M - 1)

//   说明:

//     N ≥ 1(子项行号从1开始)

//     M ≥ 1且M ≤ FieldSize(字段编号从1到FieldSize)

Array<Numeric> BQue_Queue_n_a;



// =============================================================================

// 第三部分:接口定义

// =============================================================================


// 3.1 初始化队列

// 功能:设置队列容量和字段数,并重置队列

// 输入:Queue_n_a - 队列数组,Capacity_n - 队列容量(最大可存储子项个数),FieldSize_n - 每个子项的字段数

BQue_Init(ArrayRef<Numeric> Queue_n_a, Numeric Capacity_n, Numeric FieldSize_n,Numeric Default_Value_n);


// 3.2 重置队列

// 功能:将表头[0][0]设为0,[0][1]保持不变,所有子项字段设置为Default_n

// 输入:Queue_n_a - 队列数组,Default_n - 默认填充值

BQue_Reset(ArrayRef<Numeric> Queue_n_a, Numeric Default_n);


// 3.3 入队

// 功能:将新子项添加到队尾

//       对于波峰波谷队列,不添加关键字段重复的子项(从后向前搜索,遇到小于KeyFld1_n时停止)

//       对于普通队列,只检查最后一项是否重复

//       如果队列已满,自动删除第一项

// 输入:Queue_n_a - 队列数组

//       KeyFld1_n - 关键字段1(必选)

//       KeyFld2_n - 关键字段2(FieldSize>1时使用,默认0)

//       QueueType_n - 队列类型:0=普通队列(只查最后一项),1=波峰波谷队列(从后向前搜索,默认1)

//       QV_Chk_En_n - 队列合法性检查开关:1=检查,0=不检查(默认0)

// 关键字段定义:

//   - 当 FieldSize = 1 时,关键字段为 KeyFld1_n(对应第1列)

//   - 当 FieldSize > 1 时,关键字段为 KeyFld1_n 和 KeyFld2_n(对应第1列和第2列)

// 其他字段默认填充0,可通过 BQue_SetItemField 后续设置

// 返回:1成功,-2关键字段重复,-3关键字段无效,负数其他错误码

BQue_Enqueue(ArrayRef<Numeric> Queue_n_a, Numeric KeyFld1_n, Numeric KeyFld2_n, Numeric QueueType_n, Numeric QV_Chk_En_n);


// 3.4 删除指定子项索引

// 功能:删除指定子项索引的子项,后续子项依次上移一行

//       如果 ItemIndex_n = -1,则删除最后一项

// 输入:Queue_n_a - 队列数组,ItemIndex_n - 子项索引(1 ~ 当前大小)或 -1(删除最后一项)

// 返回:1成功,-1子项索引超出有效范围,负数其他错误码

BQue_DeleteByIndex(ArrayRef<Numeric> Queue_n_a, Numeric ItemIndex_n, Numeric QV_Chk_En_n);


// 3.5 删除匹配关键字段的子项

// 功能:根据关键字段值查找匹配的子项并删除

//       支持两种队列类型的查找策略:

//       - 普通队列(QueueType_n=0):只检查最后一项

//       - 波峰波谷队列(QueueType_n=1):从后向前搜索,遇到小于KeyFld1_n时停止

//       如果找到匹配项,调用 BQue_DeleteByIndex 删除

// 输入:Queue_n_a - 队列数组

//       KeyFld1_n - 关键字段1

//       KeyFld2_n - 关键字段2(FieldSize>1时使用,默认0)

//       QueueType_n - 队列类型:0=普通队列,1=波峰波谷队列(默认1)

//       QV_Chk_En_n - 队列合法性检查开关:1=检查,0=不检查(默认0)

// 输出:返回值 - 1成功删除,0未找到匹配项,负数错误码

// 关键字段定义:

//   - 当 FieldSize = 1 时,关键字段为 KeyFld1_n(对应第1列)

//   - 当 FieldSize > 1 时,关键字段为 KeyFld1_n 和 KeyFld2_n(对应第1列和第2列)

BQue_DeleteByKey(ArrayRef<Numeric> Queue_n_a, Numeric KeyFld1_n, Numeric KeyFld2_n, Numeric QueueType_n, Numeric QV_Chk_En_n);


// 3.6 获取子项字段

// 功能:获取指定子项索引的指定字段值

//       如果 ItemIndex_n = -1,则获取最后一项(队尾)

// 输入:Queue_n_a - 队列数组,ItemIndex_n - 子项索引(1 ~ 当前大小)或 -1(最后一项)

//       FieldIndex_n - 字段编号(1 ~ FieldSize)

// 输出:Fld_Value_n - 字段值

// 返回:1成功,-1子项索引或字段索引超出有效范围,负数其他错误码

BQue_GetItemField(ArrayRef<Numeric> Queue_n_a, Numeric ItemIndex_n, Numeric FieldIndex_n, NumericRef Fld_Value_n, Numeric QV_Chk_En_n);


// 3.7 设置子项字段

// 功能:设置指定子项索引的指定字段值

//       如果 ItemIndex_n = -1,则设置最后一项(队尾)

// 输入:Queue_n_a - 队列数组,ItemIndex_n - 子项索引(1 ~ 当前大小)或 -1(最后一项)

//       FieldIndex_n - 字段编号(1 ~ FieldSize),Fld_Value_n - 字段值

// 返回:1成功,-1子项索引或字段索引超出有效范围,负数其他错误码

BQue_SetItemField(ArrayRef<Numeric> Queue_n_a, Numeric ItemIndex_n, Numeric FieldIndex_n, Numeric Fld_Value_n, Numeric QV_Chk_En_n);


// 3.8 判断队列是否已满

// 功能:判断队列是否已满(当前大小 == 容量)

// 返回:1已满,0未满,负数错误码

BQue_IsFull(ArrayRef<Numeric> Queue_n_a, Numeric QV_Chk_En_n);


// 3.9 根据关键字段获取子项索引

// 功能:根据关键字段值查找匹配的子项索引

//       支持两种队列类型的查找策略:

//       - 普通队列(QueueType_n=0):只检查最后一项

//       - 波峰波谷队列(QueueType_n=1):从后向前搜索,遇到小于KeyFld1_n时停止

// 输入:Queue_n_a - 队列数组

//       KeyFld1_n - 关键字段1

//       KeyFld2_n - 关键字段2(FieldSize>1时使用,默认0)

//       QueueType_n - 队列类型:0=普通队列,1=波峰波谷队列(默认1)

//       QV_Chk_En_n - 队列合法性检查开关:1=检查,0=不检查(默认0)

// 输出:返回值 - 找到的子项索引(1 ~ QueueSize_n),0表示未找到,负数表示错误码

// 关键字段定义:

//   - 当 FieldSize = 1 时,关键字段为 KeyFld1_n(对应第1列)

//   - 当 FieldSize > 1 时,关键字段为 KeyFld1_n 和 KeyFld2_n(对应第1列和第2列)

BQue_GetItemIdx_ByKey(ArrayRef<Numeric> Queue_n_a, Numeric KeyFld1_n, Numeric KeyFld2_n, Numeric QueueType_n, Numeric QV_Chk_En_n);


// 3.10 队列有效性检查

// 功能:检查队列的数据结构是否完整有效

//       包括:数组已初始化、字段大小有效、数组长度满足最小要求、数组结构完整

// 输入:Queue_n_a - 队列数组

// 返回:1检查通过,负数错误码

BQue_QValid_check(ArrayRef<Numeric> Queue_n_a);


// 3.11 初始化二维队列数组

// 功能:批量初始化二维队列数组中的每个一维队列(用于多数据源/多周期场景)

// 输入:Queue_aa - 二维队列数组 [图层索引][队列数据]

//       DataCount_n - 图层总数(对应data1、data2...的个数)

//       Capacity_n - 每个队列的容量(最大可存储子项个数)

//       FieldSize_n - 每个子项的字段数

//       Default_Value_n - 默认填充值

// 返回:1成功,负数错误码

// 说明:通常在策略的Init阶段调用,为每个数据图层初始化独立的队列

BQue_Init2D(ArrayRef<Array<Numeric>> Queue_aa, Numeric DataCount_n, Numeric Capacity_n, Numeric FieldSize_n, Numeric Default_Value_n);


// 3.12 获取表头字段

// 功能:获取表头列指定索引的字段值

//       表头索引从0开始,0=队列大小,1=字段数,2~HeaderSize-1=预留字段

// 输入:Queue_n_a - 队列数组,HeaderIndex_n - 表头字段索引(0 ~ HeaderSize-1)

// 输出:Hdr_Value_n - 表头字段值

// 返回:1成功,-1表头索引超出有效范围,负数其他错误码

BQue_GetHeaderField(ArrayRef<Numeric> Queue_n_a, Numeric HeaderIndex_n, NumericRef Hdr_Value_n, Numeric QV_Chk_En_n);


// 3.13 设置表头字段

// 功能:设置表头列指定索引的字段值

//       表头索引从0开始,0=队列大小,1=字段数,2~HeaderSize-1=预留字段

// 输入:Queue_n_a - 队列数组,HeaderIndex_n - 表头字段索引(0 ~ HeaderSize-1),Hdr_Value_n - 表头字段值

// 返回:1成功,-1表头索引超出有效范围,负数其他错误码

BQue_SetHeaderField(ArrayRef<Numeric> Queue_n_a, Numeric HeaderIndex_n, Numeric Hdr_Value_n, Numeric QV_Chk_En_n);



// =============================================================================

// 第四部分:函数内部变量命名

// =============================================================================


// QueueSize_n     - 队列当前有效子项个数(表头[0][0])

// FieldSize_n     - 每个子项的字段数(表头[0][1])

// HeaderSize_n    - 表头大小 = max(2, FieldSize_n)

// Array_Capacity_n - 数组总长度(GetArraySize返回值)

// Queue_Capacity_n - 队列容量(最大可存储子项个数)

// Default_Value_n  - 默认填充值

// Debug_Switch_n   - 内部调试开关(1开启,0关闭)

// QV_Chk_Res_n     - 队列合法性检查结果

// QV_Chk_En_n      - 队列合法性检查开关

// KeyFld1_n        - 关键字段1

// KeyFld2_n        - 关键字段2

// QueueType_n      - 队列类型(0=普通,1=波峰波谷)

// ItemIndex_n      - 子项索引

// FieldIndex_n     - 字段索引

// Fld_Value_n      - 字段值

// TargetIndex_n    - 转换后的目标索引

// MatchFound_n     - 匹配标志

// temp_fld_value1_n - 临时字段1值

// temp_fld_value2_n - 临时字段2值

// FoundIndex_n     - 找到的子项索引

// ai_arr_n, bj_arr_n - 循环变量



// =============================================================================

// 第五部分:注意事项

// =============================================================================


// 1. 所有删除操作都会引起后续子项依次上移一行,时间复杂度O(n * FieldSize)

// 2. 子项索引从1开始,1对应队首,最大子项索引 = 当前大小,-1表示最后一项

// 3. 字段编号从1开始,范围:1 ~ FieldSize

// 4. 表头[0][0]存当前大小,[0][1]存FieldSize,重置时[0][1]保持不变

// 5. HeaderSize = max(2, FieldSize),保证FieldSize=1时表头有2列

// 6. 内部访问公式:第N子项第M字段的数组索引 = HeaderSize + (N-1) * FieldSize + (M-1)

// 7. Init必须在首次使用前调用,指定队列容量和字段数

// 8. 关键字段定义:

//    - FieldSize=1:关键字段为第1列

//    - FieldSize>1:关键字段为第1列和第2列

// 9. 队列类型:

//    - 普通队列(0):适用于唯一性检查场景,只检查最后一项

//    - 波峰波谷队列(1):适用于时间序列数据,从后向前搜索,遇小停止

// 10. 所有对外函数都包含 QV_Chk_En_n 参数,用于控制是否进行完整性检查

// 11. 函数成功返回1,失败返回负数错误码,特殊返回值见具体函数说明


// =============================================================================

// 文档结束

// =============================================================================

如果是使用环形数组的话,就对底层结构修改一下即可


           // 【波峰波谷队列】物理存储为一维数组,逻辑层面表现为二维数组

           // 第一维:图层维度,索引为图层索引

           // 第二维:环形队列数组(核心存储层)

           // 第二维【环形队列数组】

           // 环形结构示意图

           //             FldCap

           //           ┌─────────────────────────────┐

           //           │                             │

           //           │     Header0  phy            │

           //           └─────────────────────────────┘   Phy_Idx         Seq_Idx

           //┌────────────────────────────────────────────────────────────────────┐

           //│          ┌─────────────────────────────┐                           │

           //│          │                             │                           │

           //│          │     Item1                   │     0              1      │

           //│          └─────────────────────────────┘                           │

           //│          ┌─────────────────────────────┐                           │

           //│          │     Item2                   │     1              2      │

           //│ Circular │                             │                           │

           //│          └─────────────────────────────┘                           │

           //│ Array                                                              │

           //│                 ...                                                │

           //│                 ...                                     QueCap     │

           //│                                                           -        │

           //│          ┌─────────────────────────────┐                CacheSize  │

           //│          │                             │                           │

           //│          │     Item_QueCap             │    QueCap-1               │

           //│          │                             │                           │

           //│          └─────────────────────────────┘                           │

           //└────────────────────────────────────────────────────────────────────┘


           // =========================================================================

           // 环形队列数组的定义

           // 通过一维数组模拟二维表格结构,实现环形队列特性

           // 一维数组模拟二维表格结构设计:

           // - 行:将一维数组按 FldCap 长度划分为 QueCap 段,每段为一行,分为【表头行】和【子项行】

           // - 列:每行包含 FldCap 个字段列

           // 注:后续提及的“一维数据/二维数据”均特指该模拟的二维队列结构

       

           //---------------------------------------------------------

           // - 重要参数:

           //   QueCap    - 子项行容量,取值范围 ≥ Max(CacheSize+1, 2),初始化函数设定

           //   FldCap    - 子项行字段数,取值范围 ≥ 1,与表头行总列数一致

           //   HdCap     -  HdCap = max(6, FldCap) 取值范围>=6(因表头固定6个核心列),由初始化函数设定,强调:必须使用 PVQue_CalcHdCap 函数计算

           //   CacheSize - 缓存大小,实际可用子项容量 = QueCap - CacheSize

       

           //---------------------------------------------------------

           // - 重要概念(索引命名统一):

           //   Phy_Item_Idx  - 行索引,物理行索引,对应模拟二维数组的行索引,取值范围 [0, QueCap]

           //   Phy_Idx       - 数组实际访问索引(一维数组最终寻址下标)

           //   Ring_Idx      - 环形索引,环形数组行索引,子项在环形缓冲区中的存储位置,范围 0 ~ QueCap-1

           //   Seq_Idx       - 环形序号,环形数组顺序序号行索引,子项在有效队列中的排序位置(对外暴露),范围 1 ~ Count

           //                   队首有效子项 Seq_Idx = 1,队尾有效子项 Seq_Idx = Count

           //   Fld_Idx       - 字段索引,从1开始计数(所有行的字段均按此规则)

           // 索引转换关系(模块内部使用):

           //   Ring_Idx = (Front + Seq_Idx - 1) MOD QueCap

           //   Phy_Idx  = HdCap + Ring_Idx * FldCap + (Fld_Idx - 1)

           // 【子项关键字段】

           // - 子项行第1列:KeyFld1_n(对应X_Data,X坐标)

           // - 子项行第2列:KeyFld2_n(对应Y_Data,Y坐标)

       

           //---------------------------------------------------------

           // 索引规则补充:

           //   Ring_Idx(环形索引):0 ~ QueCap-1(底层存储下标)

           //   Seq_Idx(环形序号):1 ~ Count(业务访问序号)

           // 【子项访问规则】:

           //   访问第 Seq_Idx 个有效子项的第 Fld_Idx 列:

           //     1. 计算环形索引:Ring_Idx = (Front + Seq_Idx - 1) MOD QueCap

           //     2. 计算最终物理索引:Phy_Idx  = HdCap + Ring_Idx * FldCap + (Fld_Idx - 1)

       

           // =========================================================================

           //---------------------------------------------------------

           // 【队列满处理与丢弃项保存规则】

           // - 核心要求:保留因队满被丢弃的前队首项(专属CacheSize区域存储)

           // - 队列满判定条件:Count = QueCap - CacheSize(有效子项达可用容量上限)

           // - 队列满时入队操作(核心:保留被丢弃项):

           //     1. 保留丢弃项:Front指针指向的子项位置不覆盖,作为历史丢弃项(专属存储位)

           //     2. 写入新子项:

           //           (1) 若写入位置 < Rear(环形绕回场景):先将「写入位置~Rear-1」子项整体后移1位,再写入新子项

           //           (2) 若写入位置 = Rear:直接将新子项写入该位置

           //     3. 更新指针:Rear = (Rear + 1) MOD QueCap;Front = (Front + 1) MOD QueCap

           //     4. 计数保持:Count 维持 QueCap - CacheSize 不变

           // - 丢弃项追溯公式(Insert函数调用时使用):

           //   Discard_Ring_Idx = (Front - 1 + QueCap) MOD QueCap  // 丢弃项环形索引

           //   Discard_Phy_Idx  = HdCap + Discard_Ring_Idx * FldCap + (Fld_Idx - 1)  // 丢弃项物理索引

这个算法精巧

学习了

👍

咦 点击tag 不能出现全部“造轮子”相关的帖子哎

恭喜你又找到了bug

加鸡腿加鸡腿~~~~😃

嘿嘿 tag好像彩蛋哦