是否存在类似std::count_if的单次遍历可统计多个不同属性的C++函数?
标准库目前没有内置的符合要求的多条件计数函数,std::count_if仅支持单次遍历统计单一条件的匹配次数,不过你可以自行实现一个轻量工具函数,完全满足你提到的两种调用需求。
实现1:接收谓词元组,返回计数元组(C++17及以上可用)
这个版本支持传入多个独立谓词组成的元组,最终返回对应顺序的std::ptrdiff_t类型计数元组:
#include <tuple> #include <iterator> #include <utility> template <typename Iter, typename... Preds> auto multi_count_if(Iter first, Iter last, std::tuple<Preds...> preds) { std::tuple<std::ptrdiff_t...> counts{}; for (; first != last; ++first) { std::apply([&](auto&&... pred) { std::size_t idx = 0; ((std::get<idx++>(counts) += static_cast<bool>(pred(*first))), ...); }, preds); } return counts; }
用法示例
#include <vector> #include <iostream> int main() { std::vector<int> nums = {1, 2, 3, 6, 7, 8, 10}; auto counts = multi_count_if(nums.begin(), nums.end(), std::tuple{ [](int x) { return x % 2 == 1; }, // 统计奇数数量 [](int x) { return x > 5; }, // 统计大于5的数的数量 [](int x) { return x % 2 == 0; } // 统计偶数数量 }); std::cout << "奇数个数: " << std::get<0>(counts) << "\n"; std::cout << "大于5的个数: " << std::get<1>(counts) << "\n"; std::cout << "偶数个数: " << std::get<2>(counts) << "\n"; return 0; }
实现2:接收返回bool元组的单个处理函数(C20及以上可用,可适配C17)
如果多个统计条件存在共享计算逻辑,这种写法可以避免重复计算,性能更优:
#include <tuple> #include <iterator> #include <type_traits> #include <utility> template <typename Iter, typename F> auto multi_count_if(Iter first, Iter last, F&& func) { using result_tuple_t = decltype(func(*first)); constexpr static auto tuple_size = std::tuple_size_v<result_tuple_t>; // 初始化计数元组 auto counts = []<std::size_t... Is>(std::index_sequence<Is...>) { return std::tuple<std::ptrdiff_t...>{(static_cast<void>(Is), 0)...}; }(std::make_index_sequence<tuple_size>{}); for (; first != last; ++first) { auto res = func(*first); [&]<std::size_t... Is>(std::index_sequence<Is...>) { ((std::get<Is>(counts) += static_cast<bool>(std::get<Is>(res))), ...); }(std::make_index_sequence<tuple_size>{}); } return counts; }
用法示例
#include <vector> #include <iostream> int main() { std::vector<int> nums = {1, 2, 3, 6, 7, 8, 10}; auto counts = multi_count_if(nums.begin(), nums.end(), [](int x) { // 多个条件可以共享x的前置计算结果,避免重复运算 return std::tuple{ x % 2 == 1, x > 5, x % 2 == 0 }; }); std::cout << "奇数个数: " << std::get<0>(counts) << "\n"; std::cout << "大于5的个数: " << std::get<1>(counts) << "\n"; std::cout << "偶数个数: " << std::get<2>(counts) << "\n"; return 0; }
补充说明
- 两种实现都仅做一次序列遍历,时间复杂度为O(n),空间开销仅为保存计数元组的极小成本。
- 如果需要兼容C++11/14,可以替换实现中的折叠表达式、泛型lambda为递归模板实现,核心逻辑完全一致。
- 计数结果统一使用
std::ptrdiff_t类型,和标准库std::count_if的返回类型保持对齐。
内容的提问来源于stack exchange,提问作者user12411795
相关产品推荐
相关产品推荐

