C++ 将对象移动到向量c+的前面+;

C++ 将对象移动到向量c+的前面+;,c++,vector,C++,Vector,我有一个向量finalSuggestions,它包含一个字符串单词和一些intnum 如果这个词满足某些条件,我想把这个对象移到向量的前面,把它从任何地方移走 我可以使用vector::insert for (auto &x: finalSuggestions) { if ( double((x.num)/(topword.num)) < 50) { finalSuggestions.insert(finalSuggestions.begin(),x

我有一个
向量finalSuggestions
,它包含一个
字符串
单词
和一些
int
num

如果这个词满足某些条件,我想把这个对象移到向量的前面,把它从任何地方移走

我可以使用
vector::insert

for (auto &x: finalSuggestions) {
    if ( double((x.num)/(topword.num)) < 50)
    {
        finalSuggestions.insert(finalSuggestions.begin(),x);
        break;
    }
}
我阅读了擦除-删除习惯用法(以下是我的实现):

但是我得到了一个我不理解的错误:

In instantiation of '_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = __gnu_cxx::__normal_iterator<Suggestion*, std::vector<Suggestion> >; _Tp = Suggestion]':|
在“\u FIter std::remove(\u FIter,\u FIter,const\u Tp&”)的实例化中[with\u FIter=\uu gnu\u cxx::\uu normal\u iterator;\u Tp=Suggestion]:|

对于
vector::erase
您需要迭代器,因此不能使用基于范围的
For
。使用简单的
进行循环。首先擦除元素,然后插入它,因为
insert
会使迭代器无效:

for (auto it = finalSuggestions.begin(); it != finalSuggestions.end(); ++it) {
    if (some_condition(*it)) {
        auto x = *it; // or std::move(*it)
        finalSuggestions.erase(it);
        finalSuggestions.insert(finalSuggestions.begin(), x /* or std::move(x) */);
        break;
    }
}

使用
std::move
将允许您移动元素,而不是复制它,这可能会节省一些周期。

Anton的答案是正确的。但是,如果你做了很多事情,你应该考虑不同的数据结构。
erase
insert
都是O(N)操作,其中N是
向量的大小。如果这是一个常见的操作,列表会更好

使用。这比删除和重新插入要快得多

例如:


它在功能上等同于Anton的答案,但我会使用
std::find_if
来获取要查找的元素的迭代器,而不是循环

//add #include <algorithm> to your source file

auto result = std::find_if(finalSuggestions.begin(), finalSuggestions.end(), condition_func);
if(result != finalSuggestions.end())
{
    auto resultValue = *result;
    finalSuggestions.erase(result);
    finalSuggestions.insert(finalSuggestions.begin(), resultValue);
}

如果
可用,有关
find\u的更多信息。

您的迭代器使您很难知道相关元素的位置。您可能希望尝试使用标准的
for
迭代器,该迭代器允许访问位置(由
std::vector::erase使用)

int len=finalSuggestions.size();
对于(int i=0;inum)/(topword.num))<50){
//保存项目的副本
自动项目=*它;
//删除列表中的项目
最后的建议。删除(它);
//在前面添加项目的副本
插入(finalSuggestions.begin(),项);
打破
}
}
std::vector
对象对其元素使用连续内存,这意味着在更改容器期间实际移动内存。如果你要移动周围的元素,你可能想看看或。这些容器的定义彼此几乎相同(读作:drop-in-replacements),这使得替换它们非常简单

建议:

std::deque
设计用于在容器的开头和结尾进行最佳插入。摘自cplusplus.com网站:

。。。它们提供了一种类似于向量的功能,但在序列的开头,而不仅仅是在序列的结尾,还可以有效地插入和删除元素。但是,与向量不同,DEQUE不能保证将其所有元素存储在连续的存储位置:


也许使用std::iter_交换可以解决您的问题

#include <iostream> 
#include <algorithm>
#include <vector>
using namespace std;
int main () {
vector<int> myvector{};
for(int io{}; io<7; ++io) myvector.push_back(io+1);
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
cout << ' ' << *it;
cout << '\n';
iter_swap(myvector.begin(),myvector.begin()+2);//exchange the third element with the first.
cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
 std::cout << '\n';
return 0;
}
#包括
#包括
#包括
使用名称空间std;
int main(){
向量myvector{};

对于(int-io{};ioIf
erase
花费的时间比应该的要长,您可能需要使用另一个数据结构,比如
list
也许。所谓“花费的时间比应该的要长”,我的意思是我似乎找不到解决方案,不是说运行时间变慢了。很抱歉,如果(double(*(it.num)/(topword.num))@fliposs
if(double)((it->num)/(topword.num))<50)
是的,我同意。不过,我只在相对较小的向量长度上做了一次(在得出列表更好的结论之前,我会做一些测试——大多数测试表明它不是,即使在看起来最有可能支持它的情况下也是如此。问题是,即使删除和插入是O(1),发现仍然是O(1)(N) ,而常数通常要高得多,因为它通常具有较差的引用局部性(导致较差的缓存使用)。我宁愿使用
std::find_if
来找到正确的位置,但我绝对同意使用
std::rotate
而不是插入/擦除的建议。看起来更像:到me@yachoor:分区将向量分为两部分。OP只想移动单个元素。如果目的是移动所有满足该条件的元素谓词,当然std::partition是正确的。这不应该是
std::rotate(finalSuggestions.begin(),it,finalSuggestions.end());
std::rotate(finalSuggestions.begin(),pivot,finalSuggestions.end())
,分别是?!@j00hi:No。目标是将一个元素移到向量的开头,而不是其余部分。如果不要求算法稳定,这确实是最有效的。
for (auto it = finalSuggestions.begin(), lim = finalSuggestions.end();
     it != lim;
     ++it) {
  if (it->num < 50 * topword.num) {
    std::rotate(finalSuggestions.begin(), it, it + 1);
    break;
  }
}
auto pivot = std::find_if(finalSuggestions.begin(),
                          finalSuggestions.end(),
                          [&topword](const Suggestions& s) -> bool {
                            return s.num < 50 * topword.num;
                          });
if (pivot != finalSuggestions.end()) {
  std::rotate(finalSuggestions.begin(), pivot, pivot + 1);
}
//add #include <algorithm> to your source file

auto result = std::find_if(finalSuggestions.begin(), finalSuggestions.end(), condition_func);
if(result != finalSuggestions.end())
{
    auto resultValue = *result;
    finalSuggestions.erase(result);
    finalSuggestions.insert(finalSuggestions.begin(), resultValue);
}
bool condition_func(Suggestion elementValue) { /*condition here*/ }
int len=finalSuggestions.size();
for (int i=0, ; i<len; ++i) {
    // Save a copy of the item
    auto item = finalSuggestions.at(i);
    if (double((item.num)/(topword.num)) < 50) {
        // Erase the item in the list
        finalSuggestions.erase(i);
        // Add the copy of the item back in at the front
        finalSuggestions.insert(finalSuggestions.begin(), item);
        break;
    }
}
for (auto it = finalSuggestions.begin(); it != finalSuggestions.end(); ++it) {
    if (double((*it->num)/(topword.num)) < 50) {
        // Save a copy of the item
        auto item = *it;  
        // Erase the item in the list
        finalSuggestions.erase(it); 
        // Add the copy of the item back in at the front
        finalSuggestions.insert(finalSuggestions.begin(), item); 
        break;
    }
}
#include <iostream> 
#include <algorithm>
#include <vector>
using namespace std;
int main () {
vector<int> myvector{};
for(int io{}; io<7; ++io) myvector.push_back(io+1);
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
cout << ' ' << *it;
cout << '\n';
iter_swap(myvector.begin(),myvector.begin()+2);//exchange the third element with the first.
cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
 std::cout << '\n';
return 0;
}