In one of my projects it is necessary to remove certain elements from a std::vector<double> values
. The indices I have to remove are given as a vector of intervals. For example {1,3}
means, that I have to remove indices from 1 to 3 inclusive from values
.
I can assume that the intervals given are mutually exclusive.
The code shown below illustrates, what the desired behavior should look like.
#include <iostream>
#include <vector>
int main(int argc, char** args) {
// Intervals of indices I have to remove from values
std::vector<std::pair<int, int>> intervals = { {1,3},{7,9},{13,13} };
// Vector of arbitrary values.
std::vector<double> values = {4.2,6.4,2.3,3.4,9.1,2.3,0.6,1.2,0.3,0.4,6.4,3.6,1.4,2.5,7.5 }
removeIntervals(values, intervals);
// intervals should contain 4.2,9.1,2.3,0.6,6.4,3.6,1.4,7.5
}
What might be the shortest amount of code necessary to achieve this?
My best solution so far is:
void removeIntervals(std::vector<double>& values, const std::vector < std::pair<int, int>>& intervals) {
std::vector<bool> flags(values.size(), true);
std::vector<double> ret;
for (auto interval : intervals) {
std:fill(flags.begin() + interval.first, flags.begin()+interval.second+1, false);
}
for (auto i = 0; i < values.size(); i++) {
if (flags[i]) ret.push_back(values[i]);
}
values = ret;
}
I can assume, that my intervals are non-overlapping and consecutive. It seems, that it boils down to perform erase from back to front.
void removeIntervals2(std::vector<double>& values, const std::vector < std::pair<int, int>>& intervals) {
auto revIntervals = intervals;
std::reverse(revIntervals.begin(), revIntervals.end());
for (auto interval : revIntervals) {
values.erase(std::begin(values) + interval.first, std::begin(values) + interval.second + 1);
}
}