此问题与现有问题有关:fast way to copy one vector into another
我有一个矢量源矢量S,我想创建一个目标矢量D,它只有满足特定条件的S元素(比如元素是偶数)。注意,源向量是常量向量。
我可以想到两个STL算法来做到这一点:
在这两种方法中,我都需要确保目标矢量D的大小足够大。因此,我需要创建与S大小相同的初始向量D.此外,在两种方法中,我想将向量D压缩为与其中元素数量相同的长度。我不知道哪一个更快或更方便但我不知道有条件地复制矢量的更好方法吗?
答案 0 :(得分:6)
最简单的方法是:
auto const predicate = [](int const value) { return value % 2 == 0; };
std::copy_if(begin(src), end(src), back_inserter(dest), predicate);
依赖于push_back
。
现在,确实,这可能会触发内存重新分配。不过,我想强调push_back
摊销常数的复杂性,这意味着在平均中它是O(1),这是通过拥有指数增长行为(以便执行的分配数量为O(log N))。
另一方面,如果你有100万个元素,其中只有5个是偶数,它不会预先分配4MB的内存,只能在以后只放弃20个字节。
因此:
更有趣的是,如果你预先有想法的发布,你可以使用resize
和shrink_to_fit
:
// 90% of the time, 30% of the numbers are even:
dest.reserve(src.size() * 10 / 3);
auto const predicate = [](int const value) { return value % 2 == 0; };
std::copy_if(begin(src), end(src), back_inserter(dest), predicate);
dest.shrink_to_fit();
这样:
shrink_to_fit
可能修剪多余的个人经验告诉我,对reserve
的呼吁很少(如果有的话)是值得的,摊销不变的复杂性非常有利于降低成本。
注意:shrink_to_fit
是非约束性的,没有保证让capacity
等于size
的方法,实现选择了什么' s最好的。
答案 1 :(得分:5)
好吧,你可以使用back_inserter:
std::vector<int> foo = {...whatever...};
std::vector<int> bar;
std::back_insert_iterator< std::vector<int> > back_it (bar);
std::copy_if (foo.begin(), foo.end(), back_it, MyPredicate);
或count元素:
std::vector<int> foo = {...whatever...};
int mycount = count_if (foo.begin(), foo.end(), MyPredicate);
std::vector<int> bar (mycount);
std::copy_if (foo.begin(), foo.end(), bar.begin(), MyPredicate );
第三种解决方案:
std::vector<int> foo = {...whatever...};
std::vector<int> bar (foo.size());
auto it = std::copy_if (foo.begin(), foo.end(), bar.begin(), MyPredicate );
bar.resize(std::distance(bar.begin(),it));
答案 2 :(得分:1)
copy_if
和remove_if
具有不同的语义。前者需要单独的目标向量用于匹配项
copy_if(begin(src), end(src), back_inserter(dst), myPred());
而后者删除了不匹配的商品,但仍然必须删除(删除 - 擦除习语)
src.erase(remove_if(begin(src), end(src), std::not1(myPred()), end(src));
如果您想拥有单独的目标矢量,则需要
remove_copy_if(begin(src), end(src), back_inserter(dst), std::not1(myPred()));
这应该与copy_if
同样昂贵。我会发现它更令人困惑,因为双重否定(如果不是,则删除vs复制if)。
答案 3 :(得分:0)
我个人建议使用copy_if()
。关于它的好处是它返回它停止复制的输出迭代器。以下是您提到的偶数案例的例子:
vector<int> src;
// initialize to numbers 1 -> 10
for(int i = 0; i < 10; ++i) {
src.push_back(i);
}
// set initial size to v1.size()
vector<int> dest(src.size());
// use copy_if
auto it = copy_if(src.begin(), src.end(), dest.begin(), [](int val){
return val % 2 == 0;
});
dest.resize(dest.end() - it);
这样,您只需要调整一次。