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::string
、std::vector
)。pattern
:分隔符,可以是以下類型:- 單個元素(如?
char
、int
)。 - 子范圍(如?
std::string_view
、std::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_splitauto 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:
1?
2?
3?
4
注意事項
-
子范圍生命周期:
split_view
?的子范圍是輸入范圍的視圖,確保輸入范圍在子范圍使用時仍然有效。
-
性能優化:
- 避免多次遍歷同一子范圍。若需多次使用,可將其轉換為容器(如?
std::string
、std::vector
)。
- 避免多次遍歷同一子范圍。若需多次使用,可將其轉換為容器(如?
-
C++23 的?
ranges::to
:- 若使用 C++23,可用?
ranges::to
?直接轉換子范圍:
- 若使用 C++23,可用?
#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_typefor (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 } {?! }