如何使用STL算法统计std::vector中满足指定谓词的相邻元素对数
如何使用STL算法统计std::vector中满足指定谓词的相邻元素对数
嘿,这个问题问到点子上了!你已经想到了手动循环和C++20里的std::views::pairwise,其实确实有更贴合STL风格的“非手动”做法,不用自己写累加逻辑,完全用STL算法搞定~
一、C++20及以上:用Ranges库一步到位
C++20引入的Ranges库把这种场景的处理变得特别优雅,直接结合std::views::pairwise和std::ranges::count_if就行,一行核心代码解决问题:
#include <vector> #include <ranges> #include <algorithm> // 示例谓词:判断前一个元素小于后一个 bool is_less(int a, int b) { return a < b; } int main() { std::vector<int> v = {1, 3, 2, 4, 5, 5}; // 统计满足is_less的相邻元素对数量 auto count = std::ranges::count_if( std::views::pairwise(v), [&](const auto& elem_pair) { return is_less(elem_pair.first, elem_pair.second); } ); // 这里count的结果是3:(1,3)、(2,4)、(4,5) }
原理很简单:std::views::pairwise会把原容器的相邻元素打包成一个个元素对(比如std::pair<const T&, const T&>),然后std::ranges::count_if会遍历这些元素对,自动统计满足谓词的数量——完全不用自己写循环累加,纯STL算法组合,这就是最地道的写法。
二、C++20之前:用std::accumulate实现
如果还在用C++17或更早的版本,没有Ranges库,那std::accumulate是个好选择,它可以帮我们同时跟踪计数和前一个元素,不用额外的临时容器:
#include <vector> #include <numeric> bool is_less(int a, int b) { return a < b; } int main() { std::vector<int> v = {1, 3, 2, 4, 5, 5}; if (v.size() < 2) { // 容器元素不足2个,没有相邻元素对 return 0; } // 用accumulate同时跟踪计数和前一个元素 auto result = std::accumulate( std::next(v.begin()), v.end(), std::make_pair(0, v.front()), // 初始值:计数0,前一个元素是容器第一个元素 [&](std::pair<int, int> acc, const auto& curr) { if (is_less(acc.second, curr)) { // 满足谓词,计数+1,更新前一个元素为当前元素 return std::make_pair(acc.first + 1, curr); } else { // 不满足,计数不变,更新前一个元素 return std::make_pair(acc.first, curr); } } ); auto count = result.first; // 最终统计结果 }
这里std::accumulate不再是单纯做数值累加,而是用一个pair来保存累加的状态:第一个成员是当前统计的数量,第二个成员是上一个遍历到的元素。遍历从第二个元素开始,每次和前一个元素比较,更新状态即可。
三、关于你提到的std::adjacent_find和std::adjacent_difference
你说的这两个算法确实不太适合直接统计数量:
std::adjacent_find只能找到第一个满足条件的相邻元素对,没法批量统计所有符合的情况;std::adjacent_difference虽然可以处理相邻元素,但它的核心是计算差值(或自定义二元操作的结果),如果硬要用它,得先把满足谓词的情况转换成1,不满足的转换成0,再用std::accumulate累加这些值,但这样需要额外的临时容器存储中间结果,不如前面两种方法高效简洁,所以一般不推荐这么用。
内容来源于stack exchange
相关产品推荐
相关产品推荐

