【发布时间】:2016-12-12 12:04:47
【问题描述】:
在我的一个项目中,有必要从std::vector<double> values 中删除某些元素。我必须删除的索引作为间隔向量给出。例如 {1,3} 意味着,我必须从 values 中删除从 1 到 3 的索引。
我可以假设给定的区间是互斥的。
下面显示的代码说明了所需的行为应该是什么样的。
#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
}
实现这一目标所需的最短代码量可能是多少?
到目前为止我最好的解决方案是:
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;
}
我可以假设,我的间隔是不重叠和连续的。看来,归结为从后到前执行擦除。
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);
}
}
【问题讨论】:
-
看看
std::remove_if。它实际上应该非常简单 -
在示例场景中,如果您删除 {1, 3} 和 {7, 9},您的向量将有 8 个元素,因此无法删除 {13, 13}。也许您的问题描述需要更新?
-
你能断言你的间隔不重叠吗?并且它们总是按递增顺序排列?
-
@UKMonkey 我可以保证间隔不重叠。在我的情况下,我可以假设它们是按递增顺序排列的。也许可以调用连续擦除,但是从后面开始?
-
要求最少的代码量是(1)定义不明确和(2)无意义的。最好要求高效的代码或类似的。
标签: c++ algorithm stl stdvector std-pair