Вектор C++: цикл for для std::transform

Я получил код в следующем виде

vector<int> vec{ 1,2,3 };
vector<int> vec2{ 4, 5, 6, 7, 8, 9 };

for (int i = 0; i < vec2.size(); i++) {
    if (vec2[i] % 2 == 0)
        vec.push_back(vec2[i]);
}

Как я могу использовать std::transform, чтобы избавиться от цикла for? Спасибо за помощь :)

Я попробовал что-то вроде:

std::transform(vec2.begin(), vec2.end(), std::back_inserter(vec), ...);

но я не уверен, что добавить в последнее место (где ...).

Кроме того, почему у вас проблемы с циклами? Я бы просто заменил for на более приятный: for (int value: vec2) { if (value%2==0) vec.push_back(value); }

Christian Stieber 25.06.2024 13:50

Если серьезно, мне нравится ваш код таким, какой он есть. Я могу точно видеть, что происходит.

Jason 25.06.2024 14:06

@Джейсон С std::copy_if вы также точно знаете, что происходит, плюс преимущество краткости (повышенная читабельность).

Fareanor 25.06.2024 14:07

Это ваше мнение, и это нормально. Я не согласен по поводу читабельности, но это субъективно.

Jason 25.06.2024 14:11

На мой взгляд, если в этом коде используется for на основе диапазона, он будет гораздо более читаемым, чем std::copy_if с обратной вставкой и лямбда-выражением. По крайней мере, этой лямбде следует дать имя.

Evg 25.06.2024 14:24
transform предназначен для преобразования типов элементов, а не для фильтрации.
Marek R 25.06.2024 14:24

Вы не можете быть более явным, чем «копировать, если», поскольку OP в основном хочет скопировать vec2 в vec1, если <условие> (хорошие имена в сочетании с краткостью делают читабельность)

Fareanor 25.06.2024 14:38

@Fareanor Я вижу твой аргумент и не совсем с ним согласен. Мы просто не согласны с тем, как мы определяем читабельность. Если мы предположим, что в компании полно RocketSearchers (неплохо), каждый в компании сможет прочитать исходный код и без вопросов точно понять, что происходит. Он не знал ни о std::copy_if, ни о его аргументах, ни о его предостережениях, ни о его последствиях для производительности. Так что, если он встретит это в коде, он окажет себе медвежью услугу, не остановившись и не просмотрев документацию. Так что, на мой взгляд, оригинал читабельнее.

Jason 25.06.2024 14:54

Я бы не стал использовать std::transform() для этого. Петля подойдет, но любители удаления петель могут использовать std::copy_if (vec.begin(), vec.end(), std::back_inserter(vec2),[](int x) {return x % 2 == 0; });.

Peter 25.06.2024 15:08

Вы в корне неправильно понимаете, что такое std::transform. Это не замена всех петель for. Скорее, for — это конструкция языка низкого уровня, которую можно использовать для выражения различных алгоритмов в разных диапазонах. std::transform — один из таких алгоритмов. Но цикл, который у вас есть, выражает другой алгоритм (который обычно известен как filter, но в C++ он имеет другое имя — точно так же, как C++ std::transform обычно известен под разными именами, например map).

Konrad Rudolph 25.06.2024 15:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
159
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

std::transform — неправильный инструмент для работы. Он не может фильтровать элементы по условию, все элементы из входного диапазона должны быть помещены (после преобразования) в выходной диапазон.

Вместо этого используйте std::copy_if:

std::copy_if (vec2.begin(), vec2.end(), std::back_inserter(vec), [](int i){return i % 2 == 0;});
Ответ принят как подходящий

Вам нужно std::copy_if:

    std::vector<int> vec{ 1,2,3 };
    std::vector<int> vec2{ 4, 5, 6, 7, 8, 9 };

    std::copy_if (vec2.cbegin(),vec2.cend(),std::back_inserter(vec),[](const int num){
        return num % 2 == 0;
    });
    for(auto&& i : vec) {
        std::cout << i;
    }

std::copy_if копирует элемент из одного диапазона в другой, используя предикат в качестве критерия выбора.

std::transform — это отображение одного диапазона в другой: T -> Transform -> U

Цикл вывода можно заменить на std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " ")); (при выводе vec, в противном случае вместо него выведите vec2).

Peter 25.06.2024 15:10

Было бы лучше переместить лямбду в именованную переменную isEven, чтобы было понятно, что происходит, без анализа ее тела.

Evg 25.06.2024 15:36

@Peter ostream_iterator очень шумный из-за печати такого простого вектора

Raildex 25.06.2024 22:41

@Raildex Вызов copy_if () так же шумен (особенно потому, что цикл OP можно легко записать в форме, аналогичной выходному циклу, чтобы подчеркнуть этот шум). Я хочу сказать, что если цель состоит в том, чтобы избежать (явного) написания циклов, есть варианты.

Peter 26.06.2024 03:21

Другие вопросы по теме