i have a std::vector
and a second container holding iterators or indexes (no keys, i want constant access to the element) to this vector for del
If you have a (e.g. unordered) set of indices that you want to erase, you can use this:
template <typename Type>
void erase_indices(
const std::unordered_set<size_t>& indices_to_erase,
std::vector<Type>& vec) {
std::vector<bool> erase_index(vec.size(), false);
for (const size_t i: indices_to_erase) {
erase_index[i] = true;
}
std::vector<bool>::const_iterator it_to_erase = erase_index.cbegin();
typename std::vector<Type>::iterator it_erase_from = std::remove_if(
vec.begin(), vec.end(),
[&it_to_erase](const Type&) -> bool {
return *it_to_erase++ == true;
}
);
vec.erase(it_erase_from, vec.end());
}
It is the fastest solution that came to my mind. You need C++11, though. Usage example to erase elements at index 2 and 5:
constexpr size_t num = 10u;
std::vector<int> vec(num);
std::iota(vec.begin(), vec.end(), 0);
std::unordered_set<size_t> indices_to_erase;
indices_to_erase.insert(2u);
indices_to_erase.insert(5u);
erase_indices(indices_to_erase, vec);
Before:
0 1 2 3 4 5 6 7 8 9
After:
0 1 3 4 6 7 8 9
Edit: If want to be more flexible regarding type of container that hold the indices to erase:
template <typename Type, typename Container>
void erase_indices(
const Container& indices_to_erase,
std::vector<Type>& vec) {
typedef typename Container::value_type IndexType;
static_assert(std::is_same<IndexType, std::size_t>::value,
"Indices to be erased have to be of type std::size_t");
std::vector<bool> erase_index(vec.size(), false);
for (const IndexType idx_erase: indices_to_erase) {
erase_index[idx_erase] = true;
}
std::vector<bool>::const_iterator it_to_erase = erase_index.cbegin();
typename std::vector<Type>::iterator it_erase_from = std::remove_if(
vec.begin(), vec.end(),
[&it_to_erase](const Type&) -> bool {
return *it_to_erase++ == true;
}
);
vec.erase(it_erase_from, vec.end());
}
Now you can use any kind of container from the Containers Library to provide the indices to be erased as long as the value_type
of that container is std::size_t
. Usage remains the same.