将对象移动到矢量c ++的前面

SSO*_*LIF 5 c++ vector

我有一个vector<Suggestions> finalSuggestions包含一个string word和一些int num.

如果这个单词满足某些条件,我想将该对象移动到向量的前面,将其从任何地方移除.

我能够插入到列表的开头 vector::insert

for (auto &x: finalSuggestions) {
    if ( double((x.num)/(topword.num)) < 50)
    {
        finalSuggestions.insert(finalSuggestions.begin(),x);
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道如何从列表中的位置删除它.

例如,对于某些任意向量{ 1,2,3,4,50,6,7,8,9 },如果50符合条件,则将其移动到列表的前面并将其从原处删除,然后返回{ 50,1,2,3,4,6,7,8,9 }.上面的代码返回{ 50,1,2,3,4,50,6,7,8,9 }

我正在调查vector::erase,但我遇到了问题,而且需要的时间比应该的长.

我设想一个简单的解决方案(但这显然不起作用)

for (auto &x: finalSuggestions) {
    if ( double((x.num)/(topword.num)) < 50)
    {
        finalSuggestions.insert(finalSuggestions.begin(),x);
        finalSuggestions.erase(x);
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

我读了擦除删除习语(这是我的实现):

 finalSuggestions.erase( remove( begin(finalSuggestions), end(finalSuggestions), x ), end(finalSuggestions) ); 
Run Code Online (Sandbox Code Playgroud)

但我得到一个我不明白的错误:

In instantiation of '_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = __gnu_cxx::__normal_iterator<Suggestion*, std::vector<Suggestion> >; _Tp = Suggestion]':|
Run Code Online (Sandbox Code Playgroud)

ric*_*ici 21

使用std::rotate.它比删除和重新插入要快得多.

例如:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

更好的是,正如@JerryCoffin在评论中建议的那样,std::find_if用来找到支点:

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);
}
Run Code Online (Sandbox Code Playgroud)

  • @j00hi:不。目标是将一个元素移动到开头,而不是向量的其余部分。 (2认同)

Ant*_*vin 8

因为vector::erase您需要一个迭代器,所以for不能使用基于范围的迭代器.请改用简单的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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