map,vector,sync
От: GraKon  
Дата: 10.05.17 08:03
Оценка:
нужно сделать синхронизацию контейнеров 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++;
    }
 
}
Re: map,vector,sync
От: SaZ  
Дата: 10.05.17 08:21
Оценка:
Здравствуйте, GraKon, Вы писали:

GK>нужно сделать синхронизацию контейнеров map && vector, но что-то с перебором вектора, точнее я понимаю где проблема, но не понимаю почему и как ее решить. Сильно помидорами не бросайтесь, я еще зеленый в с++. Заранее спасибо за ответ.


Что значит "синхронизацию"?
Не понятно, что у вас в векторе — ключи или значения из мапы? Почему не вектор пар (std::vector< std::pair< int, int > >)?
Re[2]: map,vector,sync
От: GraKon  
Дата: 10.05.17 08:28
Оценка:
Здравствуйте, 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))

result
vector = {8,7}
map = {(1,7),(3,8))
Re[3]: map,vector,sync
От: Кодт Россия  
Дата: 10.05.17 10:07
Оценка:
Здравствуйте, 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);
  }
}

Кто будет инлайнить всю эту тучу функций одну в другую — компилятор или шаловливые руки — тут дело хозяйское.
Перекуём баги на фичи!
Re[3]: map,vector,sync
От: AlexGin Беларусь  
Дата: 10.05.17 10:08
Оценка: 2 (1)
Здравствуйте, GraKon, Вы писали:

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))

Может вот так:
#include "stdafx.h"
#include <map>
#include <vector>
#include <algorithm>
using namespace std;

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(); )
    {
        bool bFlag = false;
        for (auto& pair : *map1)
        {
            if (pair.second == *vi)
            {
                bFlag = true;
                break;
            }
        }
        if (!bFlag)
        {
            vi = vec1->erase(vi);
            cnt++;
        }
        else
            vi++;
    }

}


int main()
{
    vector<int> vectInt{ 0,2,8,3,7 };
    map<int, int> mapInt;
    mapInt[0] = 5;
    mapInt[1] = 7;
    mapInt[2] = 9;
    mapInt[3] = 8;
    mapInt[4] = 6;
    sync(&mapInt, &vectInt);

    return 0;
}
Отредактировано 10.05.2017 10:09 AlexGin . Предыдущая версия .
Re[4]: map,vector,sync
От: GraKon  
Дата: 10.05.17 10:16
Оценка:
Здравствуйте, AlexGin, Вы писали:



AG>Может вот так:


Спасибо большое!)
Re: map,vector,sync
От: wantus  
Дата: 10.05.17 12:20
Оценка: -1
Здравствуйте, GraKon, Вы писали:

Зависит от версии стандарта и библиотеки, но

            it = map1->erase(it);


может invalidate'ать endIter.
Отредактировано 10.05.2017 12:20 wantus . Предыдущая версия .
Re[2]: map,vector,sync
От: night beast СССР  
Дата: 10.05.17 12:30
Оценка:
Здравствуйте, wantus, Вы писали:

W>Зависит от версии стандарта и библиотеки, но


W>
W>            it = map1->erase(it);
W>


W>может invalidate'ать endIter.


зачем мапе endIter инвалидировать?
Re: map,vector,sync
От: Zhendos  
Дата: 10.05.17 12:44
Оценка:
Здравствуйте, GraKon, Вы писали:

GK>нужно сделать синхронизацию контейнеров map && vector, но что-то с перебором вектора, точнее я понимаю где проблема, но не понимаю почему и как ее решить. Сильно помидорами не бросайтесь, я еще зеленый в с++. Заранее спасибо за ответ.


GK>
GK>        if( find( map1->begin(), map1->end())  == map1->end() )
GK>


Здесь просто нужно find_if написать, что-нибудь типа(если компилятор c++11
позволяет):

find_if(map1->cbegin(), map1->cend(), [vi](const std::pair<int, int> &p) {
  return p.second == *vi;
})
Re[3]: map,vector,sync
От: rg45 СССР  
Дата: 10.05.17 20:51
Оценка: +1
Здравствуйте, 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))
?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: map,vector,sync
От: AlexGin Беларусь  
Дата: 11.05.17 06:38
Оценка:
Здравствуйте, 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>?
Я вот понял, что общее количество записей (на входе в процедуру), в векторе и мапе всегда равны. Это так?
Отредактировано 11.05.2017 6:40 AlexGin . Предыдущая версия .
Re[5]: map,vector,sync
От: rg45 СССР  
Дата: 11.05.17 07:01
Оценка: +1
Здравствуйте, AlexGin, Вы писали:

AG>Я вот понял, что общее количество записей (на входе в процедуру), в векторе и мапе всегда равны. Это так?


В том-то и фокус, что постановка вопроса не достаточно четкая — остаются нюансы, которые приходится додумывать самостоятельно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: map,vector,sync
От: rg45 СССР  
Дата: 11.05.17 07:12
Оценка: +2
Здравствуйте, 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.

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: map,vector,sync
От: wantus  
Дата: 11.05.17 11:23
Оценка:
Здравствуйте, 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 был длинный флейм на эту тему, с примерами.
Re[4]: map,vector,sync
От: rg45 СССР  
Дата: 11.05.17 11:30
Оценка:
Здравствуйте, wantus, Вы писали:

W>>Зависит от версии стандарта и библиотеки, но

W>Да, я в курсе, чего там написано. Но не все же писатели std библиотек вчитываются в стандарты. На SO был длинный флейм на эту тему, с примерами.

Ну от версии стандарта это никак не зависит.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: map,vector,sync
От: night beast СССР  
Дата: 11.05.17 11:38
Оценка: +1
Здравствуйте, wantus, Вы писали:

W>Да, я в курсе, чего там написано. Но не все же писатели std библиотек вчитываются в стандарты. На SO был длинный флейм на эту тему, с примерами.


ссылка на флейм есть?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.