Search code examples
c++for-loopvectorsegmentation-faulterase

Erase elements in vector using for loop


How do I use a for loop to erase elements from a vector by its index ? I am getting a vector out of range error. I have a sample code below.

 vector<int> to_erase = {0, 1, 2}; 
 vector<int> data     = {3, 3, 3, 3};

 for(int i = 0; i < to_erase.size(); i++) {

    data.erase(data.begin() + to_erase[i]);
 }

I think it is because the size of my vector reduces through every iteration therefore it cannot access index 2.


Solution

  • You would normally employ the erase–remove idiom to delete multiple elements from a vector efficiently (erasing them one by one is generally less efficient, and, as you’ve seen, not always trivial). In its most general form, the idiom looks like this:

    data.erase(remove_algorithm(begin(data), end(data)), end(data));
    

    In your case, the remove_algorithm is based off indices in another vector, so we need to provide those as well:

    data.erase(
        remove_indices(begin(data), end(data), begin(to_erase), end(to_erase)),
        end(data));
    

    Unfortunately, such an algorithm isn’t contained in the standard library. However, it’s trivial to write yourself1:

    template <typename It, typename It2>
    auto remove_indices(It begin, It end, It2 idx_b, It2 idx_e) -> It {
        using idx_t = typename std::iterator_traits<It2>::value_type;
        std::sort(idx_b, idx_e, std::greater<idx_t>{});
    
        for (; idx_b != idx_e; ++idx_b) {
            auto pos = begin + *idx_b;
            std::move(std::next(pos), end--, pos);
        }
        return end;
    }
    

    Here, we first sort the indices to be removed from largest to smallest. Next, we loop over those indices. We then (maximally efficiently) move all elements between the current position (to be deleted) and the end of the vector forward by one. Subsequently, the end is decreased by one (to account for the fact that an element got deleted).

    Live code


    1 *Ahem* Once you’ve removed all the silly typos in your code.