2015-02-19 3 views
1

У меня есть два вектораКак удалить элементы из вектора заданного другого вектора итераторов

vector<int> vint; 
vector<vector<int>::iterator> viter; 

Что это лучший способ, чтобы удалить все элементы в vint которого итераторы присутствуют в viter. В настоящее время я временно страницы Временное решение перехода к list

Edit: (Некоторые более фона)

Это мой текущий код. Я хотел бы избежать переезда в список и вернуться к вектору

void foo(std::vector<Blah>& bvec) 
{ 
    std::list<Blah> blist; 
    std::move(bvec.begin(), bvec.end(), std::back_inserter(blist)); 
    bvec.clear(); 
    std::vector<std::list<Blah>::iterator> selectedElements; 
    { 
    //Critical section which holds a mutex. Should be as fast as possible 
    for(auto it = blist.begin(), it_end= blist.end(); it != it_end; ++it) 
    { 
     if(shouldElementBeRemoved(*it)) 
      selectedElements.push_back(it); 
    } 
    } 
    for(auto& it: selectedElements) 
    { 
    if(shouldElementReallyBeRemoved(*it)) 
     blist.erase(it); 
    } 
    std::move(blist.begin(), blist.end(), std::back_inserter(bvec)); 
} 

Может быть упрощена без списка, если можно удалить непосредственно из вектора.

void foo(std::vector<Blah>& bvec) 
{ 
    std::vector<std::vector<Blah>::iterator> selectedElements; 
    { 
    //Critical section which holds a mutex. Should be as fast as possible 
    for(auto it = bvec.begin(), it_end= bvec.end(); it != it_end; ++it) 
    { 
     if(shouldElementBeRemoved(*it)) 
      selectedElements.push_back(it); 
    } 
    } 
    for(auto& it: selectedElements) 
    { 
    if(shouldElementReallyBeRemoved(*it)) 
     // bvect.erase(it);    //Not safe! 
    } 
} 
+0

Это не для меня ясно, что вы имеете в виду под «все элементы в' vint' которых итераторы присутствуют в 'viter'» –

+0

ли эти итераторы фактически собраны из 'vint'? Зачем вам временно копировать их в «список»? Я этого не понимаю. Не работает ли простой (обратный) цикл и 'std :: vector :: erase() 'на' vint'? –

+0

Если итераторы во втором векторе указывают на vint, вы не можете использовать стирание, потому что вы собираетесь аннулировать итераторы. Однако, если итераторы указывают на другой вектор, стирание выполнит задание. –

ответ

2

Вы должны быть в состоянии использовать свой второй фрагмент с небольшой модификацией - вместо итерация selectedElements в прямом направлении, идти в обратном направлении. Тогда звонок в bvec.erase никогда не приведет к аннулированию любых итераторов, оставшихся в selectedElements.

void foo(std::vector<Blah>& bvec) 
{ 
    std::vector<std::vector<Blah>::iterator> selectedElements; 
    selectedElements.reserve(bvec.size()); // avoid growing the vector while you hold a mutex lock 

    { 
    //Critical section which holds a mutex. Should be as fast as possible 
    for(auto it = bvec.begin(), it_end= bvec.end(); it != it_end; ++it) 
    { 
     if(shouldElementBeRemoved(*it)) 
      selectedElements.push_back(it); 
    } 
    } 
    for(auto first = selectedElements.rbegin(), 
      last = selectedElements.rend(); 
      first != last; 
      ++first) 
    { 
     if(shouldElementReallyBeRemoved(**first)) 
     bvec.erase(*first); 
    } 
} 

Live demo

2

Это, казалось, сделать правильную вещь для меня:

#include <algorithm> 

    for (auto current = vint.end(); 
     current >= vint.begin();) { 
    current--; 
    if (any_of(
      viter.begin(), 
      viter.end(), 
      [current](std::vector<int>::iterator it) { 
      return current == it; 
      })) { 
     vint.erase(current); 
    } 
    } 

Использование any_of позволяет вектор итератора быть несортированный.

+1

+1 простой и простой. Хорошо подходит для небольших векторов. Не подходит для больших, поскольку сложность изменения O (N^2) – balki

1

Возможно, это было бы уместно для вашей ситуации:

struct Blah 
{ 
    bool deleted = false; // add a special field 
    // other data 
}; 

void foo(std::vector<Blah>& bvec) 
{ 
    { 
     //Critical section which holds a mutex. Should be as fast as possible 
     // mark them quickly 
     for(auto& b: bvec) 
      if(shouldElementBeRemoved(b)) 
       b.deleted = true; 
    } 

    // remove them slowly 
    for(auto i = bvec.begin(); i != bvec.end();) 
    { 
     if(i->deleted && shouldElementReallyBeRemoved(*i)) 
      i = bvec.erase(i); 
     else 
     { 
      i->deleted = false; 
      ++i; 
     } 
    } 
} 
Смежные вопросы