Союз с картой? - PullRequest
       5

Союз с картой?

1 голос
/ 08 августа 2009

Я пытаюсь объединить два набора с картой. У меня есть два комплекта, и я хотел бы объединить их в третий. Я получаю ошибку для этого кода в push_back. Есть ли способ сделать это?

map<char, vector<char> > numbers;
map<char, vector<char> >::iterator it;
numbers['E'].push_back('a');//set1
numbers['E'].push_back('b');
numbers['E'].push_back('c');
numbers['G'].push_back('d');//set2
numbers['G'].push_back('e');


void Create::Union(char set1, char set2, char set3)
{
    for (it = numbers.begin(); it != numbers.end(); ++it)
    {
        numbers[set3].push_back(it->second);
    }
}

Ответы [ 2 ]

10 голосов
/ 08 августа 2009

числа - это загрузка векторов, набранных символом. Так что это-> второй вектор. Вы не можете push_back вектор в вектор char.

Вы должны перебирать числа [set1] и числа [set2], не перебирая числа. Или, как говорит bdonlan, вы можете вставить диапазон, хотя он принимает объединение всего в числах, а не только set1 и set2.

Также: где определено item? Вы имеете в виду it?

Также обратите внимание, что push_back не проверяет, находится ли значение в векторе. Поэтому, как только вы разберетесь в деталях этого общего подхода, ваш пример будет работать, и объединение 'E' и 'G' будет вектором, содержащим 'a', 'b', 'c', 'd', «е». Но если бы вы взяли союз 'a', 'b', 'c' с 'c', 'd', 'e', ​​вы бы получили 'a', 'b', 'c', 'c', 'd', 'e', ​​что, вероятно, не то, что вы хотите от союза.

Предполагая, что ваши векторы всегда будут отсортированы, вы можете вместо этого использовать стандартный алгоритм set_union:

#include <algorithm>
#include <iterator>

...

numbers[set3].clear();
std::set_union(numbers[set1].begin(), numbers[set1].end(),
               numbers[set2].begin(), numbers[set2].end(),
               std::back_inserter(numbers[set3]));

Если вы хотите взять объединение всего в числах, я бы, вероятно, выбрал:

vector<char> sofar;
map<char, vector<char> >::iterator it;
for (it = numbers.begin(); it != numbers.end(); ++it) {
    // new, empty vector
    vector<char> target;
    // merge everything so far with the next item from the map,
    // putting the results in target
    set_union(sofar.begin(), sofar.end(),
              it->second.begin(), it->second.end(),
              back_inserter(target));
    // the result is the new "everything so far"
    // note that this operation is very fast. It doesn't have to
    // copy any of the contents of the vector, just exchange some pointers.
    swap(target, sofar);
}
// replace numbers[set3] with the final result
swap(numbers[set3], sofar);

Или:

set<char> sofar;
map<char, vector<char> >::iterator it;
for (it = numbers.begin(); it != numbers.end(); ++it) {
    // let std::set remove the duplicates for us
    sofar.insert(it->second.begin(), it->second.end());
}
// replace numbers[set3] with the final result
numbers[set3].clear();
numbers[set3].insert(numbers[set3].end(), sofar.begin(), sofar.end());

Это меньше кода и может быть быстрее, или может слишком много бить распределитель памяти. Не уверен, что лучше, а для небольших коллекций производительность почти наверняка не имеет значения.

Версия с set также не требует сортировки векторов, хотя быстрее, если они есть.

3 голосов
/ 08 августа 2009

Думаю, вы захотите:

void Create::Union(char set1, char set2, char set3)
{
    vector<char> &target = numbers[set3];
    for (it = numbers.begin(); it != numbers.end(); ++it)
    {
        if (&it->second == &target)
            continue; // Don't insert into ourselves
        target.insert(target.end(), it->second.begin(), it->second.end());
    }
}

push_back пытался добавить сам item->second вектор к целевому вектору; этот способ явно копирует только содержимое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...