删除循环内向量的元素

发布于 2024-12-22 19:39:04 字数 546 浏览 7 评论 0原文

我知道有与此类似的问题,但我未能在他们的帮助下找到我的代码的方法。我只想通过检查循环内该元素的属性来删除/删除向量的元素。我怎样才能做到这一点?我尝试了以下代码,但收到了模糊的错误消息:

“operator =”函数在“Player”中不可用。

 for (vector<Player>::iterator it = allPlayers.begin(); it != allPlayers.end(); it++)
 {
     if(it->getpMoney()<=0) 
         it = allPlayers.erase(it);
     else 
         ++it;
 }

我应该怎么办?

更新:您认为问题向量::擦除与指针成员 属于同一问题?因此我需要一个赋值运算符吗?为什么?

I know that there are similar questions to this one, but I didn’t manage to find the way on my code by their aid. I want merely to delete/remove an element of a vector by checking an attribute of this element inside a loop. How can I do that? I tried the following code but I receive the vague message of error:

'operator =' function is unavailable in 'Player’.

 for (vector<Player>::iterator it = allPlayers.begin(); it != allPlayers.end(); it++)
 {
     if(it->getpMoney()<=0) 
         it = allPlayers.erase(it);
     else 
         ++it;
 }

What should I do?

Update: Do you think that the question vector::erase with pointer member pertains to the same problem? Do I need hence an assignment operator? Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

莫言歌 2024-12-29 19:39:05

您不应在 for 循环中递增 it

for (vector<Player>::iterator it=allPlayers.begin(); 
                              it!=allPlayers.end(); 
                              /*it++*/) <----------- I commented it.
{

   if(it->getpMoney()<=0) 
      it = allPlayers.erase(it);
  else 
      ++it;
 }

请注意注释部分;此处不需要 it++,因为 it > 在 for-body 本身中逐渐增加。

至于错误“'operator =' function is unavailable in 'Player'”,它来自于内部使用 operator=< 的 erase() 的使用/code> 移动向量中的元素。为了使用 erase()Player 类的对象必须是可赋值的,这意味着您需要为 实现 operator= Player 类。

无论如何,您应该尽可能避免原始循环1尽可能并且应该更喜欢使用算法。在这种情况下,流行的擦除删除惯用语可以简化您的操作正在做。

allPlayers.erase(
    std::remove_if(
        allPlayers.begin(), 
        allPlayers.end(),
        [](Player const & p) { return p.getpMoney() <= 0; }
    ), 
    allPlayers.end()
); 

1.这是我看过的Sean Parent 的最佳演讲之一。< /sup>

You should not increment it in the for loop:

for (vector<Player>::iterator it=allPlayers.begin(); 
                              it!=allPlayers.end(); 
                              /*it++*/) <----------- I commented it.
{

   if(it->getpMoney()<=0) 
      it = allPlayers.erase(it);
  else 
      ++it;
 }

Notice the commented part;it++ is not needed there, as it is getting incremented in the for-body itself.

As for the error "'operator =' function is unavailable in 'Player’", it comes from the usage of erase() which internally uses operator= to move elements in the vector. In order to use erase(), the objects of class Player must be assignable, which means you need to implement operator= for Player class.

Anyway, you should avoid raw loop1 as much as possible and should prefer to use algorithms instead. In this case, the popular Erase-Remove Idiom can simplify what you're doing.

allPlayers.erase(
    std::remove_if(
        allPlayers.begin(), 
        allPlayers.end(),
        [](Player const & p) { return p.getpMoney() <= 0; }
    ), 
    allPlayers.end()
); 

1. It's one of the best talks by Sean Parent that I've ever watched.

沉睡月亮 2024-12-29 19:39:05
if(allPlayers.empty() == false) {
    for(int i = allPlayers.size() - 1; i >= 0; i--) {
        if(allPlayers.at(i).getpMoney() <= 0) {
            allPlayers.erase( allPlayers.begin() + i ); 
        }
    }
}

这是我删除向量中元素的方法。
它很容易理解,不需要任何技巧。

if(allPlayers.empty() == false) {
    for(int i = allPlayers.size() - 1; i >= 0; i--) {
        if(allPlayers.at(i).getpMoney() <= 0) {
            allPlayers.erase( allPlayers.begin() + i ); 
        }
    }
}

This is my way to remove elements in vector.
It's easy to understand and doesn't need any tricks.

感受沵的脚步 2024-12-29 19:39:05

忘记循环并使用 std 或 boost 范围算法。
使用 Boost.Range en Lambda 它看起来像这样:

boost::remove_if( allPlayers, bind(&Player::getpMoney, _1)<=0 );

Forget the loop and use the std or boost range algorthims.
Using Boost.Range en Lambda it would look like this:

boost::remove_if( allPlayers, bind(&Player::getpMoney, _1)<=0 );
一个人的夜不怕黑 2024-12-29 19:39:05

您的具体问题是您的 Player 类没有赋值运算符。您必须使“Player”可复制或可移动,才能将其从矢量中删除。这是因为该向量需要是连续的,因此需要对元素重新排序,以填充删除元素时产生的间隙。

另外:

如果您有 boost,请使用 std 算法

allPlayers.erase(std::remove_if(allPlayers.begin(), allPlayers.end(), [](const Player& player)
{
    return player.getpMoney() <= 0;
}), allPlayers.end());

,甚至更简单:

boost::remove_erase_if(allPlayers, [](const Player& player)
{
    return player.getpMoney() <= 0;
});

如果您不支持 C++11 lambda,请参阅 TimW 的答案。

Your specific problem is that your Player class does not have an assignment operator. You must make "Player" either copyable or movable in order to remove it from a vector. This is due to that vector needs to be contiguous and therefore needs to reorder elements in order to fill gaps created when you remove elements.

Also:

Use std algorithm

allPlayers.erase(std::remove_if(allPlayers.begin(), allPlayers.end(), [](const Player& player)
{
    return player.getpMoney() <= 0;
}), allPlayers.end());

or even simpler if you have boost:

boost::remove_erase_if(allPlayers, [](const Player& player)
{
    return player.getpMoney() <= 0;
});

See TimW's answer if you don't have support for C++11 lambdas.

暖风昔人 2024-12-29 19:39:05

或者向后循环。

for (vector<Player>::iterator it = allPlayers.end() - 1; it != allPlayers.begin() - 1; it--)
    if(it->getpMoney()<=0) 
        it = allPlayers.erase(it);

Or do the loop backwards.

for (vector<Player>::iterator it = allPlayers.end() - 1; it != allPlayers.begin() - 1; it--)
    if(it->getpMoney()<=0) 
        it = allPlayers.erase(it);
旧情勿念 2024-12-29 19:39:05

C++11 引入了将在此处使用的新函数集合。

allPlayers.erase(
    std::remove_if(allPlayers.begin(), allPlayers.end(),
        [](auto& x) {return x->getpMoney() <= 0;} ), 
    allPlayers.end()); 

然后您就可以获得不必对末端元素进行大量移动的优势。

C++11 has introduced a new collection of functions that will be of use here.

allPlayers.erase(
    std::remove_if(allPlayers.begin(), allPlayers.end(),
        [](auto& x) {return x->getpMoney() <= 0;} ), 
    allPlayers.end()); 

And then you get the advantage of not having to do quite so much shifting of end elements.

撧情箌佬 2024-12-29 19:39:05

std::vector 中删除特定元素的现代 C++20 方法如下:

std::vector vector = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::erase_if(vector, [](int const& i) { return i % 2 == 0; });

现在,所有偶数元素都从 std::vector 中删除。迭代或其他过程中索引变化没有问题。

A modern C++20 way to delete specific elements from a std::vector is as follows:

std::vector vector = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::erase_if(vector, [](int const& i) { return i % 2 == 0; });

Now all even elements are removed from the std::vector. No issues with index shifts while iterating or whatever.

毅然前行 2024-12-29 19:39:05

迟到的答案,但看到了低效的变体:

  1. std::removestd::remove_if 是要走的路。
  2. 如果由于任何原因这些不可用或因任何其他原因无法使用,请执行这些隐藏的操作。

有效删除元素的代码:

auto pos = container.begin();
for(auto i = container.begin(); i != container.end(); ++i)
{
    if(isKeepElement(*i)) // whatever condition...
    {
        if(i != pos)
        {
            *pos = *i; // will move, if move assignment is available...
        }
        ++pos;
    }
}
// well, std::remove(_if) stops here...
container.erase(pos, container.end());

您可能需要显式地编写这样的循环,例如,如果您需要迭代器本身来确定是否要删除元素(条件参数需要接受对元素的引用,还记得吗?),例如,由于与后继者/前任者的特定关系(但是,如果这种关系是相等的,则存在 std::unique)。

Late answer, but as having seen inefficient variants:

  1. std::remove or std::remove_if is the way to go.
  2. If for any reason those are not available or cannot be used for whatever other reason, do what these hide away from you.

Code for removing elements efficiently:

auto pos = container.begin();
for(auto i = container.begin(); i != container.end(); ++i)
{
    if(isKeepElement(*i)) // whatever condition...
    {
        if(i != pos)
        {
            *pos = *i; // will move, if move assignment is available...
        }
        ++pos;
    }
}
// well, std::remove(_if) stops here...
container.erase(pos, container.end());

You might need to write such a loop explicitly e. g. if you need the iterator itself to determine if the element is to be removed (the condition parameter needs to accept a reference to element, remember?), e. g. due to specific relationship to successor/predecessor (if this relationship is equality, though, there is std::unique).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文