2015-03-05 4 views
1

Если я хочу, чтобы получить декартово произведение этих двух vector<string> с:Создайте декартово произведение 2 векторов <string> s На месте?

vector<string> final{"a","b","c"}; 
vector<string> temp{"1","2"}; 

Но я хочу, чтобы поместить результат в final, так что окончательный будет содержать:

a1
a2
b1
b2
c1
c2

Я бы хотел сделать это без создания временного массива. Можно ли сделать это? Если это имеет значение, порядок final не имеет значения.

+2

@ FrédéricHamidi Декартовой продукт и застежка-молнии - это разные вещи. –

+0

@ T.C., Вы правы, не знаете, о чем я думал. Голосование отведено. –

+0

Это слишком много, чтобы скопировать 'final' во временный объект до того, как' final' будет изменен на месте? –

ответ

3

Вы можете попробовать следующий подход

#include <iostream> 
#include <vector> 
#include <string> 

int main() 
{ 
    std::vector<std::string> final{ "a", "b", "c" }; 
    std::vector<std::string> temp{ "1", "2" }; 

    auto n = final.size(); 

    final.resize(final.size() * temp.size()); 

    for (auto i = n, j = final.size(); i != 0; --i) 
    { 

     for (auto it = temp.rbegin(); it != temp.rend(); ++it) 
     { 
      final[--j] = final[i-1] + *it; 
     } 

    } 

    for (const auto &s : final) std::cout << s << ' '; 
    std::cout << std::endl; 

    return 0; 
} 

Выход программы

a1 a2 b1 b2 c1 c2 
+0

Я думал, что у меня было лучшее [решение] (http://stackoverflow.com/a/28902562/2642059), чем вы вызываете его меньше разветвления (Я думал?) Но ваше решение быстрее каждый раз, поэтому я принял его. Любые мысли о том, почему вы быстрее? Неужели это разделение намного медленнее? –

+0

@ Jonathan Mee Я думаю, что разница связана с избыточными операциями% и /. –

+0

Думаю, это имеет смысл. Я ожидал, что компилятор разделит их на одну операцию. Думаю нет. Во всяком случае, хорошее решение, спасибо. –

0

Попробуйте функцию декартову:

#include <vector> 
#include <string> 

using namespace std; 

void cartesian(vector<string>& f, vector<string> &o) { 
int oldfsize = f.size(); 
f.resize(oldfsize * o.size()); 
for (int i = o.size() - 1; i>=0; i--) { 
    for (int j = 0; j < oldfsize; j++) { 
    f[i*oldfsize + j] = f[j] + o[i]; 
    } 
} 
} 


int main() 
{ 
vector<string> f{"a","b","c"}; 
vector<string> temp{"1","2"}; 
cartesian(f, temp); 
for (auto &s: f) { 
    printf("%s\n", s.c_str()); 
} 
} 
+0

Это круто! :) для (auto & s: f) { printf ("% s \ n", s.c_str()); } –

+0

рад, что вам нравится;) C++ 11 rulez;) –

0

Это работает для меня:

void testCartesianString(vector<string>& final, 
         vector<string>const& temp) 
{ 
    size_t size1 = final.size(); 
    size_t size2 = temp.size(); 

    // Step 1. 
    // Transform final to : {"a","a","b","b","c","c"} 
    final.resize(size1*size2); 
    for (size_t i = size1; i > 0; --i) 
    { 
     for (size_t j = (i-1)*size2; j < i*size2; ++j) 
     { 
     final[j] = final[i-1]; 
     } 
    } 

    // Step 2. 
    // Now fix the values and 
    // change final to : {"a1","a2","b1","b2","c1","c2"} 
    for (size_t i = 0; i < size1; ++i) 
    { 
     for (size_t j = 0; j < size2; ++j) 
     { 
     final[i*size2+j] = final[i*size2+j] + temp[j]; 
     cout << final[i*size2+j] << " "; 
     } 
     cout << endl; 
    } 
} 
+0

Это был мой первый подход, но если вы собираетесь потратить время на инициализацию в отдельном цикле, похоже, вы должны использовать. 'final [i * size2 + j] + = temp [j];' вместо 'final [i * size2 + j] = final [i * size2 + j] + temp [j];' В любом случае, я думаю [ Влад из Москвы] (http://stackoverflow.com/users/2877241/vlad-from-moscow) - это немного лучше, поскольку он касается только одного элемента один раз. –

0

Это вариант только для личных предпочтений Vald from Moscow. Я думаю, что это может быть быстрее для динамических массивов, потому что будет меньше разветвлений. Но я не собираюсь писать тестовый стенд.

Учитывая входы vector<string> final и vector<string> temp:

const auto size = testValues1.first.size(); 

testValues1.first.resize(size * testValues1.second.size()); 

for (int i = testValues1.first.size() - 1; i >= 0; --i){ 
    testValues1.first[i] = testValues1.first[i % size] + testValues1.second[i/size]; 
} 

EDIT:

Неа, это решение медленнее, не быстрее: http://ideone.com/e.js/kVIttT

И обычно значительно быстрее, хотя я не знать почему ...

В любом случае, предпочитайте Vlad from Moscow ответ