0

Take this code:

using ColumnIndexVector = std::vector<int>;
ColumnIndexVector m_vColumnIndexesToExclude;

bool bModified = false;

for (int iColumn = 1; iColumn < m_Grid.GetColumnCount(); iColumn++)
{
    if (m_bNotUsed) // Not used
    {
        if (m_vColumnIndexesToExclude.erase(iColumn) > 0)
        {
            bModified = true;
        }
    }
}

The line if (m_vColumnIndexesToExclude.erase(iColumn) > 0) will not compile. I complains that iColumn is not a ColumnIndexVector.

How can I remove a number if it exists in the vector?

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164

1 Answers1

1

This is the error that my compiler says (after adding definitions that you forgot):

error: no matching function for call to 'std::vector<int>::erase(int&)'
   22 |         if (m_vColumnIndexesToExclude.erase(iColumn) > 0)
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/vector:67,
                 from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_vector.h:1430:7: note: candidate: 'std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::const_iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = std::vector<int>::iterator; std::vector<_Tp, _Alloc>::const_iterator = std::vector<int>::const_iterator]'
 1430 |       erase(const_iterator __position)
      |       ^~~~~
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_vector.h:1430:28: note:   no known conversion for argument 1 from 'int' to 'std::vector<int>::const_iterator'
 1430 |       erase(const_iterator __position)
      |             ~~~~~~~~~~~~~~~^~~~~~~~~~

As the compiler explains to you, there is no erase function that would accept an int as an argument. There is an erase function that accepts an iterator. The iterator is what you must pass to erase an element from a vector.

The typical way to erase all elements with particular value is the erase-remove idiom. With certain pre-conditions you have more efficient options available:

  • If the container is sorted, then you can do binary search using std::lower_bound for single element or std::equal_range for multiple.
  • If the container isn't sorted and you don't need to keep the order, then you can do a linear search, swap with last element, and pop_back.

However, considering the apparent use case, an unsorted vector would be an inefficient choice. std::unordered_set would likely be more efficient if there are many indices.

eerorika
  • 232,697
  • 12
  • 197
  • 326