You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ranges::views::chunk_by时能否引用当前子范围并实现限长递增分块?

解决方案

你的核心问题是ranges::views::chunk_by的谓词只能访问相邻元素,无法跟踪当前块的大小,所以没法直接在谓词里同时满足「连续递增1」和「块大小不超过4」两个条件。下面提供两种基于Ranges库的实现方式:

方法一:组合视图(推荐)

先把序列分割成最大的连续递增块,再将每个大块拆分为最多4个元素的子块,最后展平结果。这种方式无状态、符合Ranges组合式编程的设计理念,代码可读性和可维护性都更好:

#include <ranges>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1,2,3,4,5,6,8,9,10,11,12,15};
    
    auto result = v 
                 | std::ranges::views::chunk_by([](int a, int b) { return a + 1 == b; })
                 | std::ranges::views::transform([](auto continuous_chunk) {
                     return continuous_chunk | std::ranges::views::chunk(4);
                   })
                 | std::ranges::views::join;

    // 输出验证
    for (auto subrange : result) {
        for (int num : subrange) {
            std::cout << num << " ";
        }
        std::cout << "\n";
    }
}

逻辑拆解

  1. chunk_by:将原序列分割为最大的连续递增1的块(比如示例中的[1,2,3,4,5,6]、[8,9,10,11,12]、[15]);
  2. transform + chunk(4):对每个大块进行二次分割,确保每个子块的大小不超过4;
  3. join:将嵌套的子块视图展平为一层,得到最终符合要求的分块结果。

方法二:带状态的分割谓词

如果希望一步完成分割,可以自定义带状态的谓词配合split_when实现,但这种方式的视图不支持多次遍历(状态会保留):

#include <ranges>
#include <vector>
#include <iostream>

struct SplitRule {
    int current_chunk_size = 1; // 初始值为1,因为第一个元素已计入当前块

    bool operator()(int prev, int curr) {
        // 元素不连续,分割并重置块大小
        if (prev + 1 != curr) {
            current_chunk_size = 1;
            return true;
        }
        // 元素连续但当前块已达4个元素,分割并重置
        if (current_chunk_size >= 4) {
            current_chunk_size = 1;
            return true;
        }
        // 元素连续且块大小未超限,增大块大小,不分割
        ++current_chunk_size;
        return false;
    }
};

int main() {
    std::vector<int> v = {1,2,3,4,5,6,8,9,10,11,12,15};
    auto result = v | std::ranges::views::split_when(SplitRule{});

    // 输出验证
    for (auto subrange : result) {
        for (int num : subrange) {
            std::cout << num << " ";
        }
        std::cout << "\n";
    }
}

注意事项

  • 该方法的视图只能遍历一次,因为SplitRule中的current_chunk_size状态会在遍历过程中修改;
  • 如果需要多次遍历,每次都要创建新的SplitRule实例。

内容的提问来源于stack exchange,提问作者Sungtaek Lim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:17:50