当前位置: 首页 > news >正文

std::ranges::views::split, lazy_split, std::ranges::split_view, lazy_split_view

std::ranges::views::split, std::ranges::split_view

C++20 中引入的用于分割范围(range)的组件,允许将输入范围按特定分隔符或条件分割成多个子范围。以下是详细说明和示例:


基本概念

1. 功能
  • 分割范围:将输入范围(如字符串、容器)按指定的分隔符(可以是单个元素、子范围或谓词)分割成多个子范围。
  • 惰性求值split_view 是惰性适配器,只有在遍历时才会执行分割操作,不会预先分配内存。
  • 返回类型:返回一个 split_view 对象,其元素是 subrange 类型的子范围。

语法与参数

1. 语法
auto split_view = input_range | std::ranges::views::split(pattern);

 

  • input_range:输入范围(如 std::stringstd::vector)。
  • pattern:分隔符,可以是以下类型:
    • 单个元素(如 charint)。
    • 子范围(如 std::string_viewstd::vector)。
    • 谓词(需满足 std::indirect_unary_predicate)。

示例

示例 1:使用字符分割字符串
#include <iostream>
#include <ranges>
#include <string>
#include <vector>

using namespace std;

int main() {
    string str = "apple,banana,cherry";
    // 使用 views::split 替代 views::lazy_split
    auto split_view = str | views::split(',');

    for (auto const& word : split_view) {
        // 正确转换子范围到字符串的两种方式:
        
        // 方式 1:使用 ranges::to(C++23 特性)
        // cout << ranges::to<string>(word) << endl;
        
        // 方式 2:传统构造方式(兼容 C++20)
        cout << string{word.begin(), word.end()} << endl;
    }
}

output:

apple
banana
cherry

示例 2:使用子范围分割字符串
#include <iostream>
#include <ranges>
#include <string>

int main() {
    std::string str = "apple::banana::cherry";
    std::string_view delimiter = "::";
    auto split_view = str | std::ranges::views::split(delimiter);

    for (const auto& subrange : split_view) {
        std::string word{subrange.begin(), subrange.end()};
        std::cout << word << "\n";
    }
}
示例 3:处理空子范围

当输入以分隔符开头或结尾时,会产生空子范围:

#include <iostream>
#include <ranges>
#include <string>

int main() {
    std::string str = ",apple,,banana,";
    auto split_view = str | std::ranges::views::split(',');

    for (const auto& subrange : split_view) {
        std::string word{subrange.begin(), subrange.end()};
        std::cout << (word.empty() ? "[empty]" : word) << "\n";
    }
}

outpu:

[empty]
apple
[empty]
banana
[empty]

示例 4:分割容器
#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> data = {1, 0, 2, 0, 3, 0, 4};
    auto split_view = data | std::ranges::views::split(0);

    for (const auto& subrange : split_view) {
        std::vector<int> segment{subrange.begin(), subrange.end()};
        for (int num : segment) std::cout << num << " ";
        std::cout << "\n";
    }
}

output:




4

注意事项

  1. 子范围生命周期

    • split_view 的子范围是输入范围的视图,确保输入范围在子范围使用时仍然有效。
  2. 性能优化

    • 避免多次遍历同一子范围。若需多次使用,可将其转换为容器(如 std::stringstd::vector)。
  3. C++23 的 ranges::to

    • 若使用 C++23,可用 ranges::to 直接转换子范围:
#include <ranges>
std::cout << std::ranges::to<std::string>(subrange) << "\n";

总结

  • 核心用途:高效分割范围,无需内存拷贝。
  • 适用场景:处理字符串分割、日志解析、数据流分析等。
  • 关键接口views::split 和 split_view,结合 subrange 迭代器操作。

std::ranges::views::lazy_split, std::ranges::lazy_split_view

 C++20 引入的惰性范围适配器,用于将输入范围按指定分隔符分割成多个子范围。它不会立即执行分割,而是在遍历时动态生成子范围,适用于处理大型数据或需要延迟计算的场景。

基本用法

  • 头文件<ranges>

  • 语法input_range | views::lazy_split(pattern)

  • 参数:

    • input_range: 要分割的范围(如字符串、容器等)。

    • pattern: 分隔符,可以是单个元素或一个子范围。

示例代码

示例 1:
#include <algorithm>
#include <iostream>
#include <ranges>
#include <string_view>
 
auto print = [](auto const& view)
{
    // `view` is of std::views::lazy_split_view::__outer_iterator::value_type
 
    for (std::cout << "{ "; const auto element : view)
        std::cout << element << ' ';
    std::cout << "} ";
};
 
int main()
{
    constexpr static auto source = {0, 1, 0, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9};
    constexpr int delimiter{0};
    constexpr std::ranges::lazy_split_view outer_view{source, delimiter};
    std::cout << "splits[" << std::ranges::distance(outer_view) << "]:  ";
    for (auto const& inner_view: outer_view)
    {
        print(inner_view);
    }
 
    constexpr std::string_view hello{"Hello C++ 20 !"};
    std::cout << "\n" "substrings: ";
    //std::ranges::for_each(hello | std::views::lazy_split(' '), print);
    const auto substr = hello | std::views::lazy_split(' ');
    for (auto const& str: substr)
    {
        print(str);
    }
 
    constexpr std::string_view text{"Hello-+-C++-+-20-+-!"};
    constexpr std::string_view delim{"-+-"};
    std::cout << "\n" "substrings: ";
    std::ranges::for_each(text | std::views::lazy_split(delim), print);
}

Output:

splits[5]:  { } { 1 } { 2 3 } { 4 5 6 } { 7 8 9 }
substrings: { H e l l o } { C + + } { 2 0 } { ! }
substrings: { H e l l o } { C + + } { 2 0 } { ! }

相关文章:

  • vs2022用git插件重置--删除更改(--hard)后恢复删除的内容
  • 深入解析Go语言Channel:源码剖析与并发读写机制
  • 高级定时器的解码器模式
  • upload-labs-靶场(1-19关)通关攻略
  • python-leetcode 50.岛屿数量
  • 颤抖:quiver,shiver,tremble的区别
  • 火绒终端安全管理系统V2.0--分层防御之行为拦截层
  • Benewake(北醒) 快速实现TF-NOVA IIC接口与电脑通信的操作说明
  • 电子文档安全管理系统 V6.0 resources/backup存在任意文件下载漏洞(DVB-2025-8794)
  • 数据结构与算法:归并排序
  • AIM-T500绝缘监测仪:实时监测,确保IT系统绝缘安全-安科瑞 蒋静
  • 2025-03-12 学习记录--C/C++-PTA 习题10-11 有序表的增删改查操作
  • 论数组去重之高效方法
  • ai讲angular rxjs
  • [023-01-40].第40节:组件应用 - OpenFeign与 Sentinel 集成实现fallback服务降级
  • C++ 中的 static_assert 编译期断言使用
  • AnythingLLM的局域网发布
  • CLR中的marshal_as 介绍
  • MPAndroidChart的MarkerView和CursorLineChartRenderer同步显示当前触摸的数据点
  • JavaScript泄露浏览器插件信息引发的安全漏洞及防护措施
  • 一个多月来上海交大接连“牵手”三区,在这些方面进行区校合作
  • 广州地铁十一号线赤沙车辆段工程高坠事故调查报告公布:1人重伤且漏报
  • 讲一个香港儿童的故事,《劏房的天空》获“周庄杯”特等奖
  • 2024年度全国秋粮收购达3.45亿吨
  • 礼来公布头对头研究详细结果:替尔泊肽在所有减重目标中均优于司美格鲁肽
  • 巴基斯坦全面恢复领空开放