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

是否存在类似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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:48:00