✈️ Алгоритмы диапазонов: Алгоритмы поиска — 27 мая 2026 г. в 17:37:00.651
✈️ Алгоритмы диапазонов: Алгоритмы поиска Продолжаем разбираться в диапазонах 🙂 std::ranges::* — это переработанные алгоритмы из <algorithm>. Они принимают диапазоны целиком (не нужно писать begin/end) и поддерживают проекции. 👁 ranges::find / ranges::find_if — найти элемент std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6}; // Найти первый элемент, равный 4 auto it = std::ranges::find(v, 4); if (it != v.end()) { std::cout << "Найдено: " << *it << "\n"; // 4 } // Найти первый элемент, удовлетворяющий условию auto it2 = std::ranges::find_if(v, [](int x) { return x > 5; }); // указывает на 9 ❗️ Возвращают итератор на найденный элемент или end(), если ничего не найдено. В отличие от классического std::find, диапазонная версия принимает контейнер целиком — никаких v.begin(), v.end(). ↗️ ranges::all_of / any_of / none_of — проверки на весь диапазон std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6}; bool all_positive = std::ranges::all_of(v, [](int x) { return x > 0; }); // true — все элементы положительные bool any_gt_8 = std::ranges::any_of(v, [](int x) { return x > 8; }); // true — есть 9 bool none_neg = std::ranges::none_of(v, [](int x) { return x < 0; }); // true — отрицательных нет Три алгоритма, одна идея: проверить предикат на всём диапазоне. Ленивые — all_of остановится на первом false, any_of — на первом true. 🧋 ranges::count / ranges::count_if — подсчёт auto count_ones = std::ranges::count(v, 1); // 2 auto count_big = std::ranges::count_if(v, [](int x) { return x > 5; }); // 2 (9, 6) count — точное совпадение, count_if — по предикату. Возвращают std::ranges::range_difference_t, а не int — на практике это обычно ptrdiff_t. 🍪 ranges::minmax_element — минимум и максимум за один проход auto [min_it, max_it] = std::ranges::minmax_element(v); std::cout << *min_it << " " << *max_it; // 1 9 Возвращает пару итераторов {min, max}. Один проход вместо двух отдельных вызовов min_element + max_element. Structured bindings (auto [min_it, max_it]) делают код чище. ❗️ Также доступны ranges::min_element и ranges::max_element по отдельности. А ranges::min / ranges::max возвращают копию значения (не итератор и не ссылку) — учитывайте это для тяжёлых объектов. 🍕 Проекции — суперсила ranges-алгоритмов struct Person { std::string name; int age; }; std::vector<Person> people = {{"Алиса", 30}, {"Борис", 25}, {"Вера", 35}}; // Найти человека по имени — без лямбды! auto it = std::ranges::find(people, "Борис", &Person::name); // it->age == 25 // Самый молодой auto youngest = std::ranges::min_element(people, {}, &Person::age); // youngest->name == "Борис" // Все ли совершеннолетние? bool all_adults = std::ranges::all_of(people, [](int a) { return a >= 18; }, &Person::age); Проекция — третий (или четвёртый) аргумент. Она «извлекает» нужное поле перед сравнением. Больше не нужно писать громоздкие лямбды вида [](const Person& p) { return p.age; } — достаточно &Person::age. ❗️ Обратите внимание: в find мы передаём std::string{"Борис"}, а не строковый литерал. Литерал "Борис" имеет тип const char*, и хотя неявное преобразование в std::string здесь сработает, явная конструкция делает намерение очевидным. 🩹 Комбинируем с views std::map<std::string, std::vector<int>> data = { {"alpha", {1, 2, 3}}, {"beta", {4, 5}}, {"gamma", {6, 7, 8, 9}}, }; // Сколько значений больше 5 во всех векторах? auto all_values = data | views::values | views::join; auto count = std::ranges::count_if(all_values, [](int x) { return x > 5; }); // 4 (6, 7, 8, 9) views::values извлекает вторые элементы пар (векторы), а views::join разворачивает один уровень вложенности — склеивает все векторы в единый плоский диапазон. Результат можно передать в любой ranges-алгоритм.

