Преобразование двух векторов int одинаковой длины в один вектор пар int в C++

В С++, если у меня есть два вектора int:

A = [1, 2, 3 ,4]; 
B = [1, 2, 3, 4]; 

Как я могу объединить их в один вектор пар:

[(1,1), (2,2), (3,3), (4, 4)]

Конечно, я могу сделать это с помощью цикла. Но можем ли мы сделать это, используя подходящие функции STL и итераторы?


person David Ren    schedule 28.08.2013    source источник
comment
Думаю, у Boost есть stackoverflow.com/questions/8511035 /   -  person Karthik T    schedule 28.08.2013
comment
stackoverflow.com/questions/17287107 /   -  person Karthik T    schedule 28.08.2013


Ответы (2)


Для этого можно использовать алгоритм:

std::vector<std::pair<int, int>> target;
target.reserve(A.size());
std::transform(A.begin(), A.end(), B.begin(), std::back_inserter(target),
               [](int a, int b) { return std::make_pair(a, b); });
person Dietmar Kühl    schedule 28.08.2013
comment
Обратите внимание, что на самом деле это не помогает избавиться от цикла. Цикл будет просто скрыт в std::transform(). Кроме того, в этом конкретном случае явный цикл был бы короче и понятнее. - person Karadur; 28.08.2013
comment
@Karadur: вы не можете применить операцию к N элементам без какой-либо итерации по элементам, что совершенно очевидно: сжатие двух последовательностей невозможно выполнить за O (1). Также совершенно ясен вопрос о том, что требуется: можем ли мы сделать это, используя подходящие функции STL и итераторы?. Этот ответ делает именно это. - person David Rodríguez - dribeas; 28.08.2013
comment
Вы могли бы даже не использовать лямбду и использовать make_pair напрямую, не так ли? - person jrok; 28.08.2013
comment
@jrok: я так не думаю, поскольку make_pair не будет допустимым функтором, make_pair<int, int>, с другой стороны, может действительно работать… Это также не сработает, поскольку реализация make_pair основана на универсальных ссылках, которые становятся ссылками rvalue, если вы возьмете вычитание из типа… - person MFH; 28.08.2013
comment
@MFH Да, я не имел в виду без параметров шаблона. Что-то вроде make_pair<int&,int&> должно работать, хотя на это немного странно смотреть. - person jrok; 28.08.2013
comment
@jrok: это действительно работает (благодаря сворачиванию ссылок). Лично я бы предпочел лямбда-версию… - person MFH; 28.08.2013
comment
@jrok: использование лямбда-выражения упрощает встраивание операции, а использование указателя функции, т. е. std::make_pair() напрямую, — нет. - person Dietmar Kühl; 28.08.2013
comment
@Karadur: Хотя, вероятно, это не так, std::transform() можно реализовать рекурсивно или с помощью подходящей магии. Однако да, любое решение будет использовать цикл или эквивалентную конструкцию. - person Dietmar Kühl; 28.08.2013

Я согласен с тем, что ответ Дитмара Кюля именно соответствует тому, что было задано в вопросе, но я также согласен с комментарием Какадура. Цикл скрыт в std::transform(), поэтому сложность такая же. Некоторые люди осудят меня, но если нет прямых доказательств того, что один способ лучше другого, я предпочитаю наиболее читаемый и наименее подробный вариант:

// create a vector of length of the smaller vector
std::vector<std::pair<int, int>> target( A.size() < B.size() ? A.size() : B.size() );

for (unsigned i = 0; i < target.size(); i++)
    target[i] = std::make_pair(A[i], B[i]);

P.S. Приведенный выше код выделяет достаточно места для вектора target, так что можно избежать потенциальных накладных расходов push_back (в случае перераспределения).

person Oleksiy    schedule 28.08.2013
comment
знаете, в push_back также скрыта потенциальная петля - person David Brown; 28.08.2013
comment
Ну да, но если произойдет перераспределение. Спасибо за подсказку, я обновлю свой ответ - person Oleksiy; 28.08.2013
comment
Однако для большинства людей эта версия гораздо более читабельна и понятна - Да, для тех, кто не знаком со стандартной библиотекой (и, следовательно, с C++). И это вообще не отвечает на вопрос, не так ли? - person Christian Rau; 28.08.2013
comment
@ChristianRau Ваше предположение не имеет смысла. Я знаком со стандартной библиотекой и C++, но этот код мне кажется более читабельным и понятным. Как минимум 3 других человека проголосовали, так что я не одинок. Этот код действительно отвечает на вопрос (я использую подходящие функции STL - например, std::make_pair). Я просто отказываюсь использовать код STL, если он не имеет меньшей сложности и лучшей читабельности. Я не буду использовать STL вслепую, особенно если это выглядит более многословно и некрасиво. Простота здесь ключ к успеху, мой друг :) - person Oleksiy; 28.08.2013
comment
Ну, по крайней мере, вы убрали утверждение, что большинству людей это покажется более читаемым и понятным. Но, к сожалению, это ничего не меняет в безответности поста. Ответы существуют не для того, чтобы признать первоначальный вопрос некорректным, для этого и нужны комментарии. Вы вполне можете счесть его подход неуместным и привести для этого веские основания, но это ничего не меняет в обоснованности и возможности ответа на его вопрос. Конечно, он хочет использовать стандартный библиотечный алгоритм вместо цикла, независимо от того, хотите ли этого вы тоже. - person Christian Rau; 17.09.2013