Есть ли хороший способ удалить элементы в векторе или deque? предоставить пример кода более чем приветствуется - PullRequest
1 голос
/ 28 марта 2011

Например, я хорошо 2 вектора, скажем, вектор тока, вектор to_delete.Есть ли хороший способ удалить элементы, которые появляются в текущем.

Вот мой способ сделать это.Я думаю, это не выглядит хорошо.Поэтому, пожалуйста, помогите мне.Спасибо.

#include <iostream>
#include <vector>
using namespace std;
int main(){
  vector <double> current;
  current.push_back(1.1);
  current.push_back(2.1); 
  current.push_back(3.1); 
  current.push_back(4.1); 
  current.push_back(5.1); 
  current.push_back(6.1); 
  current.push_back(7.1); 
  current.push_back(8.1);
  vector <double> to_delete;
  to_delete.push_back(2.1);
  to_delete.push_back(5.1);
  for(int i = 0;i<to_delete.size();i++){
    int loc = -1;
    for(int j = 0; j < current.size();j++)
    {
      if(current[j]==to_delete[i]){
        loc = j;
        break;
      }
    }
    if(loc >= 0){
      current.erase(current.begin()+loc);
    }
  }

  for(int i = 0;i < current.size();i++){
    cout << current[i]<< endl;
  }
}

Ответы [ 4 ]

5 голосов
/ 28 марта 2011

Вероятно, самый простой способ - создать новый вектор, используя std::set_difference (оба вектора должны быть отсортированы для работы):

std::vector<double> diff;
std::set_difference(current.begin(), current.end(),
                    to_delete.begin(), to_delete.end(),
                    std::back_inserter(diff));
2 голосов
/ 28 марта 2011

Что не так с чем-то вроде:

std::vector<double>::iterator iter
    = std::find_first_of( current.begin(), current.end(),
                          to_delete.begin(), to_delete.end() );
while ( iter != current.end() ) {
    iter = std::find_first_of( current.erase( iter ), current.end(),
                               to_delete.begin(), to_delete.end() );
}

Также вы можете определить предикат:

template <typename Container>
class IsElementOf
{
    Container const* m_container;
public:
    IsElementOf(Container const& container)
        : m_container(&container)
    {
    }

    bool operator()( typename Container::value_type const& v ) const
    {
        return std::find( m_container->begin(),
                          m_container->end(),
                          v )
                != m_container->end();
    }
};

template <typename Container>
inline IsElementOf<Container>
isElementOf( Container const& container )
{
    return IsElementOf<Container>(container);
}

и использовать std :: remove_if:

current.erase(
    std::remove_if( current.begin(), current.end(),
                    isElementOf( to_delete ) ),
    current.end() );

(Это действительно только правильное предложение, если вам нужно делать подобные вещи в разных местах. Или если вы можете использовать boost :: bind для генерации IsElementOf, но это сложно, потому что компилятор победил 'Не знаю, с чего начать, когда нужно выяснить тип, поэтому вам придется явно указать его где-нибудь.)

0 голосов
/ 28 марта 2011

Во-первых, вы должны заметить, что в вашем конкретном примере x.1 НЕ полностью представлен в формате с двумя базовыми числами с плавающей запятой, и что попытка сравнить эти значения может привести к неравенству из-за кода, сгенерированного компилятором, даже если кажется, чтоэто должно работать.

Далее, действительно ли vector является правильным контейнером, если вам нужно произвольное удаление, подобное этому?Рассматривали ли вы вместо этого set или multiset?

Если вам нужен контейнер с произвольным доступом, вы можете использовать метод set_difference, предложенный @ Space_C0wb0y, или использовать std::remove:

for(int i = 0;i<to_delete.size();i++)
{
    current.erase(std::remove(current.begin(), current.end(), to_delete[i]), current.end());
}

Предполагая n = current.size() и m = to_delete.size(), если он уже отсортирован, set_difference должен быть линейным.Если он не отсортирован, это будет O(n log n) + O(m log m).Подход удаления будет O(m n)

0 голосов
/ 28 марта 2011

Вы можете использовать std::find() вместо ручной петли, чтобы найти позицию элемента, который должен быть удален.

std::vector<double>::iterator del =
      std::find(current.begin(), current.end(), to_delete[i]);
if (del != current.end())
    current.erase(del);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...