Учитывая входную последовательность, стандартные алгоритмы std::count
и std::accumulate
подсчитывают количество событий определенного значения (или совпадение предикатов для std::count_if
) и накопление данной ассоциативной операции (sum, product, Boolean или/и, min/max, конкатенация строк и т.д.), соответственно.
Что, если кто-то хочет знать, содержит ли входная последовательность ровно/по крайней мере/не более n
встреча/совпадения или накапливается до суммы точно/не менее/не более n
? Метод грубой силы - сравнить результат std::count
или std::accumulate
с целевым n
, но это пропустит возможность раннего выхода, когда количество или накопление превысит цели уже на полпути через входную последовательность.
Можно, например, сделайте count_until
как
template<class InputIt, class T, class Pred>
auto count_until(InputIt first, InputIt last, const T& value, Pred pred)
{
auto res = 0;
for (; first != last; ++first)
if (*first == value && pred(++res))
break; // early exit if predicate is satisfied
return std::make_pair(first, res); // iterator and value to allow continuation
}
и из которого можно было бы проверить равенство/по крайней мере/не более, используя подходящий предикат и сравнение с возвращаемым счетом.
Вопросы:
- можно написать
count_until
(и аналогично дляaccumulate_until
) с использованием комбинации существующих стандартных алгоритмов, возможно, в сочетании с подходящим Boost.Iterator? - В частности, я думал о
find_if
надaccumulate_iterator
, где предикат извлекал бы счет или сумму из итератора. - Или выполнить
count_until
иaccumulate_until
включение в качестве автономных примитивов в будущей версии стандартной библиотеки?
Изменить. Я считаю, что наиболее полезной формулировкой является возвращение std::pair
итератора и счетчика в точке, где предикат сначала выполняется. Это позволяет пользователям продолжить итерацию.