Spec-Zone.ru › C++

std::count, std::count_if

Определено в заголовке <algorithm>
(1)
template< class InputIt, class T >
typename iterator_traits<InputIt>::difference_type
    count( InputIt first, InputIt last, const T& value );
(до C++20)
template< class InputIt, class T >
constexpr typename iterator_traits<InputIt>::difference_type
    count( InputIt first, InputIt last, const T& value );
(с C++20)
template< class ExecutionPolicy, class ForwardIt, class T >
typename iterator_traits<ForwardIt>::difference_type
    count( ExecutionPolicy&& policy,
           ForwardIt first, ForwardIt last, const T& value );
(2) (с C++17)
(3)
template< class InputIt, class UnaryPredicate >
typename iterator_traits<InputIt>::difference_type
    count_if( InputIt first, InputIt last, UnaryPredicate p );
(до C++20)
template< class InputIt, class UnaryPredicate >
constexpr typename iterator_traits<InputIt>::difference_type
    count_if( InputIt first, InputIt last, UnaryPredicate p );
(с C++20)
template< class ExecutionPolicy, class ForwardIt, class UnaryPredicate >
typename iterator_traits<ForwardIt>::difference_type
    count_if( ExecutionPolicy&& policy,
              ForwardIt first, ForwardIt last, UnaryPredicate p );
(4) (с C++17)

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

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

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> является true.

(до C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> является true.

(с C++20)

Параметры

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

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

Требования к типу
-InputIt должен удовлетворять требованиям LegacyInputIterator.
-ForwardIt должен удовлетворять требованиям LegacyForwardIterator.

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

Количество итераторов it в диапазоне [first, last) удовлетворяющих следующему условию:

1,2) *it == value является true.
3,4) p(*it) != false является true.

Сложность

Учитывая N как std::distance(first, last):

1,2) Точно N сравнений с value с использованием operator==.
3,4) Точно N применений предиката p.

Исключения

Перегрузки с параметром шаблона, названным ExecutionPolicy сообщают об ошибках следующим образом:

  • Если выполнение функции, вызванной как часть алгоритма, вызывает исключение, и ExecutionPolicy является одной из стандартных политик, вызывается std::terminate . Для любой другой ExecutionPolicy, поведение определяется реализацией.
  • Если алгоритм не удается выделить память, выбрасывается std::bad_alloc .

Примечания

О количестве элементов в диапазоне [first, last) без дополнительных критериев см. std::distance.

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

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

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

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

Пример

#include <algorithm>
#include <array>
#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);
}

Вывод:

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
удалено требование

См. также

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

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

Spec-Zone.ru

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