нужно сделать синхронизацию контейнеров map && vector, но что-то с перебором вектора, точнее я понимаю где проблема, но не понимаю почему и как ее решить. Сильно помидорами не бросайтесь, я еще зеленый в с++. Заранее спасибо за ответ.
void sync(std::map<int, int> *map1, std::vector<int>* vec1)
{
std::map<int, int>::iterator it = map1->begin();
std::map<int, int>::iterator endIter = map1->end();
int cnt=0;
for (; it != endIter; )
{
if ( find(vec1->begin(), vec1->end(), it->second) == vec1->end()) {
it = map1->erase(it);
cnt++;
}
else {
++it;
}
}
for( std::vector<int>::iterator vi = vec1->begin(); vi != vec1->end(); )
{
if( find( map1->begin(), map1->end()) == map1->end() )
{
vi = vec1->erase( vi );
cnt++;
}
else
vi++;
}
}
Здравствуйте, GraKon, Вы писали:
GK>нужно сделать синхронизацию контейнеров map && vector, но что-то с перебором вектора, точнее я понимаю где проблема, но не понимаю почему и как ее решить. Сильно помидорами не бросайтесь, я еще зеленый в с++. Заранее спасибо за ответ.
Что значит "синхронизацию"?
Не понятно, что у вас в векторе — ключи или значения из мапы? Почему не вектор пар (std::vector< std::pair< int, int > >)?
Здравствуйте, SaZ, Вы писали:
SaZ>Что значит "синхронизацию"? SaZ>Не понятно, что у вас в векторе — ключи или значения из мапы? Почему не вектор пар (std::vector< std::pair< int, int > >)?
Вектор и мапа рандомно заполняются значениями. Мне нужно проверить эти контейнеры на одинаковые значение между ними(vector-map). В мапе нужно проверять только значение(second), ключи на нужны. И нужно оставить только дубликаты, а все остальное удалить.
vector = {0,2,8,3,7}
map = {(0,5),(1,7)(2,9)(3,8)(4,6))
Здравствуйте, GraKon, Вы писали:
GK>Вектор и мапа рандомно заполняются значениями. Мне нужно проверить эти контейнеры на одинаковые значение между ними(vector-map). В мапе нужно проверять только значение(second), ключи на нужны. И нужно оставить только дубликаты, а все остальное удалить. GK>vector = {0,2,8,3,7} GK>map = {(0,5),(1,7)(2,9)(3,8)(4,6))
GK>result GK>vector = {8,7} GK>map = {(1,7),(3,8))
Тут многое зависит от размеров вектора и мапа, и от количества сохраняемых / удаляемых элементов.
Для больших контейнеров делать предикат "значение присутствует" путём линейного забега каждый раз — дорого. Лучше один раз собрать значения в быстрый ассоциативный контейнер (unordered_set).
Кроме того, — можно не удалять ненужные элементы, а скопировать нужные. Это дороже по памяти, но безопаснее в плане ошибок.
В общем, я бы вот так сделал:
using Map = std::map<int, int>;
using Vec = std::vector<int>;
template<class Pred>
void keep_map_items_if(Map& m, Pred&& p) {
// удаляющий способfor (Map::iterator i = m.begin(); i != m.end(); )
if (p(*i))
++i;
else
i = m.erase(i);
// копирующий способ
Map tmp;
std::copy_if(m.begin(), m.end(), p, std::inserter(tmp));
tmp.swap(m);
}
template<class Pred>
void keep_vector_items_if(Vec& v, Pred&& p) {
// удаляющий способ (вместо поштучного удаления, как в твоём коде)
v.erase(
std::remove_if(v.begin(), v.end(), std::not1(p)), // в С++17 будет std::not_fn
v.end()
);
// копирующий способ - такой же!
Vec tmp;
std::copy_if(v.begin(), v.end(), p, std::inserter(tmp));
tmp.swap(v);
}
using Set = std::unordered_set<int>;
Set values_of_map(const Map& m) {
Set s(v.size()); // резервируем количество корзин наобум (заведомо достаточное)for (const Map::item_type& kv : m)
s.insert(kv.second);
return s;
}
Set values_of_vector(const Vec& v) {
return Set(v.begin(), v.end(), v.size());
}
void keep_map_items_present_in_vector(Map& m, const Vec& v) {
Set s = values_of_vector(v);
keep_map_items_if(m, [&s](const Map::item_type kv) { return s.find(kv.second) != s.end(); });
}
void keep_vector_items_present_in_map(Vec& v, const Map& m) {
Set s = values_of_map(m);
keep_vector_items_if(v, [&s](int e) { return s.find(e) != s.end(); });
}
// ну а теперь всё вместе (и ещё позволим себе алгоритмическую оптимизацию)void keep_same_items(Map& m, Vec& v) {
if (v.size() < m.size()) {
keep_map_items_present_in_vector(m, v);
keep_vector_items_present_in_map(v, m);
} else {
keep_vector_items_present_in_map(v, m);
keep_map_items_present_in_vector(m, v);
}
}
Кто будет инлайнить всю эту тучу функций одну в другую — компилятор или шаловливые руки — тут дело хозяйское.
Здравствуйте, GraKon, Вы писали:
GK>нужно сделать синхронизацию контейнеров map && vector, но что-то с перебором вектора, точнее я понимаю где проблема, но не понимаю почему и как ее решить. Сильно помидорами не бросайтесь, я еще зеленый в с++. Заранее спасибо за ответ.
GK>
Здравствуйте, GraKon, Вы писали:
GK>Вектор и мапа рандомно заполняются значениями. Мне нужно проверить эти контейнеры на одинаковые значение между ними(vector-map). В мапе нужно проверять только значение(second), ключи на нужны. И нужно оставить только дубликаты, а все остальное удалить. GK>vector = {0,2,8,3,7} GK>map = {(0,5),(1,7)(2,9)(3,8)(4,6)) GK>result GK>vector = {8,7} GK>map = {(1,7),(3,8))
А что должно получиться на выходе, если на входе что-то типа такого:
vector = {7,7,7,7,7}
map = {(1,7)(2,7)(3,7))
?
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, GraKon, Вы писали:
GK>Вектор и мапа рандомно заполняются значениями. Мне нужно проверить эти контейнеры на одинаковые значение между ними(vector-map). В мапе нужно проверять только значение(second), ключи на нужны. И нужно оставить только дубликаты, а все остальное удалить. GK>vector = {0,2,8,3,7} GK>map = {(0,5),(1,7)(2,9)(3,8)(4,6)) GK>result GK>vector = {8,7} GK>map = {(1,7),(3,8))
R>А что должно получиться на выходе, если на входе что-то типа такого: R>vector = {7,7,7,7,7} R>map = {(1,7)(2,7)(3,7)) R>?
Я вот понял, что общее количество записей (на входе в процедуру), в векторе и мапе всегда равны. Это так?
Здравствуйте, wantus, Вы писали:
W>Зависит от версии стандарта и библиотеки, но W>
W> it = map1->erase(it);
W>
W>может invalidate'ать endIter.
С самого начала, начиная со стандарта C++98, в требованиях к ассоциативным контейнерам присутствует такой пункт:
23.1.2/8
The insert members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>С самого начала, начиная со стандарта C++98, в требованиях к ассоциативным контейнерам присутствует такой пункт: R>
R>23.1.2/8
R>The insert members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.
Да, я в курсе, чего там написано. Но не все же писатели std библиотек вчитываются в стандарты. На SO был длинный флейм на эту тему, с примерами.
Здравствуйте, wantus, Вы писали:
W>>Зависит от версии стандарта и библиотеки, но W>Да, я в курсе, чего там написано. Но не все же писатели std библиотек вчитываются в стандарты. На SO был длинный флейм на эту тему, с примерами.
Ну от версии стандарта это никак не зависит.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, wantus, Вы писали:
W>Да, я в курсе, чего там написано. Но не все же писатели std библиотек вчитываются в стандарты. На SO был длинный флейм на эту тему, с примерами.