Spec-Zone.ru › C++

std::count, std::count_if

Определено в заголовочном файле <algorithm>
template< class InputIt, class T >
typename std::iterator_traits<InputIt>::difference_type
    count( InputIt first, InputIt last, const T& value );
(1) (constexpr с C++20)
(до C++26)
template< class InputIt, class T = typename std::iterator_traits
                                       <InputIt>::value_type >
constexpr typename std::iterator_traits<InputIt>::difference_type
    count( InputIt first, InputIt last, const T& value );
(начиная с C++26)
template< class InputIt, class UnaryPred >
typename std::iterator_traits<InputIt>::difference_type
    count_if( InputIt first, InputIt last, UnaryPred p );
(2) (constexpr с C++20)
template< class ExecutionPolicy, class ForwardIt, class T >
typename std::iterator_traits<ForwardIt>::difference_type
    count( ExecutionPolicy&& policy,
           ForwardIt first, ForwardIt last, const T& value );
(3) (начиная с C++17)
(до C++26)
template< class ExecutionPolicy,
          class ForwardIt, class T = typename std::iterator_traits
                                         <ForwardIt>::value_type >
typename std::iterator_traits<ForwardIt>::difference_type
    count( ExecutionPolicy&& policy,
           ForwardIt first, ForwardIt last, const T& value );
(начиная с C++26)
template< class ExecutionPolicy, class ForwardIt, class UnaryPred >
typename std::iterator_traits<ForwardIt>::difference_type
    count_if( ExecutionPolicy&& policy,
              ForwardIt first, ForwardIt last, UnaryPred p );
(4) (начиная с C++17)

Возвращает количество элементов исходного диапазона [first, last), удовлетворяющих заданным критериям.

1) Подсчитывает элементы, равные value (с использованием operator==).
2) Подсчитывает элементы, для которых предикат p возвращает true.
3,4) То же, что и (1,2), но выполняется в соответствии с policy.
Эти перегрузки участвуют в разрешении перегрузки только в том случае, если значение следующего выражения равно true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(до C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(начиная с C++20)

Параметры

first, last - пара итераторов, задающих исходный диапазон
value - значение, которое нужно найти
p - унарный предикат, который возвращает ​true для требуемых элементов.

Выражение p(v) должно быть преобразуемо в bool для каждого аргумента v типа (возможно, const) VT, где VT — тип значения InputIt, независимо от категории значения, и не должно изменять v. Поэтому тип параметра VT& не допускается, как и VT, если только для VT перемещение не эквивалентно копированию(начиная с C++11). ​

policy - политика выполнения, которую следует использовать
Требования к типам
-InputIt должен удовлетворять требованиям LegacyInputIterator.
-ForwardIt должен удовлетворять требованиям LegacyForwardIterator.
-UnaryPred должен удовлетворять требованиям Predicate.

Возвращаемое значение

Количество итераторов iter в исходном диапазоне, удовлетворяющих следующему условию:

1,3) *iter == value равно true.
2,4) p(*iter) != false равно true.

Сложность

Пусть \(\scriptsize N\)N — это std::distance(first, last):

1) Ровно \(\scriptsize N\)N сравнений с value с использованием operator==.
2) Ровно \(\scriptsize N\)N вызовов p.
3) \(\scriptsize \mathcal{O}(N)\)𝓞(N) сравнений с value с использованием operator==.
4) \(\scriptsize \mathcal{O}(N)\)𝓞(N) вызовов p.

Исключения

3,4) Во время выполнения:
  • Если требуемые для распараллеливания временные ресурсы памяти недоступны, выбрасывается std::bad_alloc.
  • Если при доступе к объектам через аргумент алгоритма выбрасывается неперехваченное исключение, поведение определяется политикой выполнения (для стандартных политик вызывается std::terminate).

Примечания

Чтобы узнать количество элементов в диапазоне без дополнительных критериев, см. std::distance.

Макрос проверки поддержки возможностей Значение Стандарт Возможность
__cpp_lib_algorithm_default_value_type 202403 (C++26) Инициализация списком для алгоритмов (1,3)

Возможная реализация

См. также реализации count в libstdc++ и libc++.

См. также реализации count_if в libstdc++ и libc++.

count
template<class InputIt, class T = typename std::iterator_traits<InputIt>::value_type>
typename std::iterator_traits<InputIt>::difference_type
    count(InputIt first, InputIt last, const T& value)
{
    typename std::iterator_traits<InputIt>::difference_type ret = 0;
    for (; first != last; ++first)
        if (*first == value)
            ++ret;
    return ret;
}
count_if
template<class InputIt, class UnaryPred>
typename std::iterator_traits<InputIt>::difference_type
    count_if(InputIt first, InputIt last, UnaryPred p)
{
    typename std::iterator_traits<InputIt>::difference_type ret = 0;
    for (; first != last; ++first)
        if (p(*first))
            ++ret;
    return ret;
}

Пример

#include <algorithm>
#include <array>
#include <cassert>
#include <complex>
#include <iostream>
#include <iterator>

int main()
{
    constexpr std::array v{1, 2, 3, 4, 4, 3, 7, 8, 9, 10};
    std::cout << "v: ";
    std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    
    // Determine how many integers match a target value.
    for (const int target : {3, 4, 5})
    {
        const int num_items = std::count(v.cbegin(), v.cend(), target);
        std::cout << "number: " << target << ", count: " << num_items << '\n';
    }
    
    // Use a lambda expression to count elements divisible by 4.
    int count_div4 = std::count_if(v.begin(), v.end(), [](int i) { return i % 4 == 0; });
    std::cout << "numbers divisible by four: " << count_div4 << '\n';
    
    // A simplified version of “distance” with O(N) complexity:
    auto distance = [](auto first, auto last)
    {
        return std::count_if(first, last, [](auto) { return true; });
    };
    static_assert(distance(v.begin(), v.end()) == 10);
    
    std::array<std::complex<double>, 3> nums{{{4, 2}, {1, 3}, {4, 2}}};
    #ifdef __cpp_lib_algorithm_default_value_type
        // T gets deduced making list-initialization possible
        auto c = std::count(nums.cbegin(), nums.cend(), {4, 2});
    #else
        auto c = std::count(nums.cbegin(), nums.cend(), std::complex<double>{4, 2});
    #endif
    assert(c == 2);
}

Вывод:

v: 1 2 3 4 4 3 7 8 9 10
number: 3, count: 2
number: 4, count: 2
number: 5, count: 0
numbers divisible by four: 3

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были ретроспективно применены к ранее опубликованным стандартам C++.

DR Применён к Поведение согласно опубликованной версии Исправленное поведение
LWG 283 C++98 Требовалось, чтобы T удовлетворял требованиям EqualityComparable, но
тип значения InputIt не всегда является T
требование удалено

См. также

ranges::countranges::count_if
(C++20)(C++20)
возвращает количество элементов, удовлетворяющих заданным критериям
(объект-функция алгоритма)
distance
возвращает расстояние между двумя итераторами
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/count

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API