Объединить пару элементов из одного вектора с другим элементом
Есть вектор vector<vector<string> >kosz, в котором хранятся векторы с разным количеством элементов. Есть еще один вектор vector<vector<string> >pairs;, в нем хранятся элементы из вектора kosz, но разбитые по парам по принципу из этого вопроса. Нужно создать еще один вектор, или же это может быть словарь, в который нужно поместить пару элементов из вектора pairs и еще один элемент из вектора kosz. То есть должно быть примерно так: kosz {{a,b,c,d}, {b,c,d}, pairs{{a,b},{b,c}, {c,d}, {b,d}} и словарь к примеру в котором будут хранится {{a,b},{c}},{{a,b},{d}},{{b,c},d},{{b,c},a},{{c,d},a},{{c,d},b},{{b,d},c},{{b,d},c} ну и в таком роде. Получается пара + третий элемент(причем нужно перебрать все возможные элементы, которые могут быть третьими(в пределах проверяемого вектора, за исключением пары элементов, которые уже в нем имеются)). Надеюсь понятно изложил. Начал пробовать, вот что получилось. В общем, ошибка в том что перебирает не все пары из вектора pairs, в котором хранятся уникальные пары слов и выбивает, что происходит стирание элементов, где-то за пределами вектора, не пойму почему так.
vector<vector<string> >kosz;// здесь хранятся все элементы, по описанию выше
vector<vector<string> >pairs; // вектор с уникальными парами из вектора kosz
vector<string>pairs_vec_all; // вектор, в котором храню все слова из другого вектора
map<pair<string, string>, string> triple_combo;// это уже словарь, в котором хранятся все возможные комбинации
//заполняю вектор словами
for (int i = 0; i < kosz.size(); i++) {
for (int j = 0; j < kosz[i].size(); j++)
{
cout << "push kosz[i][j]): " << kosz[i][j] << endl;
pairs_vec_all.push_back(kosz[i][j]);
}
cout << "\n" << endl;
for (int i = 0; i < pairs.size(); i++) {
for (int j = 0; j < 1; j++) {
//если слова совпадают, то нужно стереть каждое
if (pairs[i][0] == pairs[i][1])
{
auto it = std::find(pairs_vec_all.begin(), pairs_vec_all.end(), pairs[i][0]);
auto pos = it - pairs_vec_all.begin();
auto iter = pairs_vec_all.end();
int pos1 = 0;
if (it != pairs_vec_all.end())
{
auto iter = std::find(pairs_vec_all.begin() + pos, pairs_vec_all.end(), pairs[i][1]);
auto pos1 = iter - pairs_vec_all.begin();
}
if (it != pairs_vec_all.end() || iter != pairs_vec_all.end())
{
pairs_vec_all.erase(pairs_vec_all.begin() + pos);
pairs_vec_all.erase(pairs_vec_all.begin() + pos1);
pairs_vec_all.resize(std::distance(pairs_vec_all.begin(), pairs_vec_all.end()));
}
}
else {
auto it = std::find(pairs_vec_all.begin(), pairs_vec_all.end(), pairs[i][0]);
auto pos = it - pairs_vec_all.begin();
auto iter = std::find(pairs_vec_all.begin(), pairs_vec_all.end(), pairs[i][1]);
auto pos1 = iter - pairs_vec_all.begin();
if (it != pairs_vec_all.end() || iter != pairs_vec_all.end())
{
cout << "pos: " << pos << endl;
cout << "pos1: " << pos1 << endl;
cout << "pairs: " << pairs[i][0] << ", " << pairs[i][1] << endl;
pairs_vec_all.erase(pairs_vec_all.begin() + pos);
pairs_vec_all.erase(pairs_vec_all.begin() + pos1);
pairs_vec_all.resize(std::distance(pairs_vec_all.begin(), pairs_vec_all.end()));
}
}
}
for (auto it = pairs_vec_all.begin(); it != pairs_vec_all.end(); ++it) // вывод на экран
cout << ' ' << *it;
cout << "\n" << endl;
pair<string, string> pr(pairs[i][0], pairs[i][1]);
for (int i = 0; i < pairs_vec_all.size(); i++)
{
cout << "pr: " << pr.first << ", " << pr.second << ", pairs_vec_all: " << pairs_vec_all[i] << endl;
triple_combo[pr] = pairs_vec_all[i]; // здесь формируются уже пары в словаре + третье слово
}
pairs_vec_all.clear();
cout << "cleared... " << pairs_vec_all.size() << endl;
}
}
Ответы (1 шт):
Ох, если я правильно понял то, что твориться в Вашем коде, то Вам нужно собрать все уникальные сочетания пар из вектора пар pairs и всех строк из kosz (далее data) и без повторов строк в кортеже. Я позволил себе использовать std::vector<std::pair...>> для вектора пар:
#include <string>
#include <unordered_set>
#include <vector>
auto tripleCombo(const std::vector<std::vector<std::string>> &data,
const std::vector<std::pair<std::string, std::string>> &pairs)
{
std::unordered_set<std::pair<std::pair<std::string, std::string>, std::string>> result;
for (const auto &strings : data) {
for (const auto &item : strings) {
for (const auto &pair : pairs) {
if (pair.first != item && pair.second != item)
result.emplace(std::make_pair(pair, item));
}
}
}
return result;
}
Если ожидается, что data содержит много повторов, то можно сделать предобработку data - переложить всё в std::unordered_set<std::string>.
PS: Если у вас ещё нет вычисления хеша от std::pair, придётся добавить, либо использовать простой set:
namespace std {
template <typename A, typename B>
struct hash<std::pair<A, B>>
{
std::size_t operator()(const std::pair<A, B> &value) const noexcept
{
return std::hash<A>{}(value.first) ^ (std::hash<B>{}(value.second) << 1); // or use boost::hash_combine
}
};
} // namespace std