Я получил код в следующем виде
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), ...);
но я не уверен, что добавить в последнее место (где ...).
Если серьезно, мне нравится ваш код таким, какой он есть. Я могу точно видеть, что происходит.
@Джейсон С std::copy_if вы также точно знаете, что происходит, плюс преимущество краткости (повышенная читабельность).
Это ваше мнение, и это нормально. Я не согласен по поводу читабельности, но это субъективно.
На мой взгляд, если в этом коде используется for на основе диапазона, он будет гораздо более читаемым, чем std::copy_if с обратной вставкой и лямбда-выражением. По крайней мере, этой лямбде следует дать имя.
transform предназначен для преобразования типов элементов, а не для фильтрации.
Вы не можете быть более явным, чем «копировать, если», поскольку OP в основном хочет скопировать vec2 в vec1, если <условие> (хорошие имена в сочетании с краткостью делают читабельность)
@Fareanor Я вижу твой аргумент и не совсем с ним согласен. Мы просто не согласны с тем, как мы определяем читабельность. Если мы предположим, что в компании полно RocketSearchers (неплохо), каждый в компании сможет прочитать исходный код и без вопросов точно понять, что происходит. Он не знал ни о std::copy_if, ни о его аргументах, ни о его предостережениях, ни о его последствиях для производительности. Так что, если он встретит это в коде, он окажет себе медвежью услугу, не остановившись и не просмотрев документацию. Так что, на мой взгляд, оригинал читабельнее.
Я бы не стал использовать std::transform() для этого. Петля подойдет, но любители удаления петель могут использовать std::copy_if (vec.begin(), vec.end(), std::back_inserter(vec2),[](int x) {return x % 2 == 0; });.
Вы в корне неправильно понимаете, что такое std::transform. Это не замена всех петель for. Скорее, for — это конструкция языка низкого уровня, которую можно использовать для выражения различных алгоритмов в разных диапазонах. std::transform — один из таких алгоритмов. Но цикл, который у вас есть, выражает другой алгоритм (который обычно известен как filter, но в C++ он имеет другое имя — точно так же, как C++ std::transform обычно известен под разными именами, например map).





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).
Было бы лучше переместить лямбду в именованную переменную isEven, чтобы было понятно, что происходит, без анализа ее тела.
@Peter ostream_iterator очень шумный из-за печати такого простого вектора
@Raildex Вызов copy_if () так же шумен (особенно потому, что цикл OP можно легко записать в форме, аналогичной выходному циклу, чтобы подчеркнуть этот шум). Я хочу сказать, что если цель состоит в том, чтобы избежать (явного) написания циклов, есть варианты.
Кроме того, почему у вас проблемы с циклами? Я бы просто заменил
forна более приятный:for (int value: vec2) { if (value%2==0) vec.push_back(value); }