【问题标题】:how to remove all even integers from set<int> in c++如何从 C++ 中的 set<int> 中删除所有偶数
【发布时间】:2011-01-06 12:08:52
【问题描述】:

我是 C++ 新手。我想知道有经验的编码员是如何做到这一点的。

我有什么:

set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(5);

for(set<int>::iterator itr = s.begin(); itr != s.end(); ++itr){
if (!(*itr % 2))
    s.erase(itr);
}

当然,它不起作用。因为它在擦除后递增。 这是否意味着每次我从集合中删除元素后,Itr 都必须指向集合的开头?

【问题讨论】:

    标签: c++ set stdset


    【解决方案1】:
     for(set<int>::iterator itr = s.begin(); itr != s.end(); ){
      if (!(*itr % 2))
          s.erase(itr++);
    
      else ++itr;
     }
    

    Scott Myers 的有效 STL

    【讨论】:

    • 为什么在擦除函数中允许itr++,而在外部不允许?
    • itr++ 允许在外面使用,但++it 通常在未使用该值时更可取,因为每次有人这样做时都会很乏味;-) 在这种情况下,忽略通常的良好做法并写itr++ 可能会更好,因为如果在两种情况下都相同,代码读起来会稍微流畅一些。
    【解决方案2】:

    从 std::set 中删除元素只会使指向该元素的迭代器无效。

    在擦除目标元素之前获取下一个元素的迭代器。

    【讨论】:

      【解决方案3】:

      您无需回到起点。 set::erase 只会使引用被擦除项目的迭代器无效,因此您只需在擦除之前复制迭代器并递增:

      for(set<int>::iterator itr = s.begin(); itr != s.end();)
      {
          set<int>::iterator here = itr++;
          if (!(*here % 2))
              s.erase(here);
      }
      

      【讨论】:

      • 好吧,我放弃了。什么错误?
      • 我错了,我以为你跳过了第一个元素。我收回我的评论并投反对票。
      【解决方案4】:

      最好的办法是结合使用remove_if和erase

      s.erase(remove_if(s.begin(), s.end(), evenOddFunctor), s.end())
      

      这会很有帮助 http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

      另请参阅 scott meyers 的有效 STL

      Edit: 虽然我的解决方案是错误的,但我不会删除它。对于像我这样不了解可变/不可变迭代器的人来说,这可能是一个很好的学习

      【讨论】:

      • remove_if 要求 operator* 返回一个非常量左值。 std::set 强制它始终是有序的;从std::set::operator* 返回一个非常量左值会破坏该保证。因此std::remove_if() 不占用std::set::iterators
      • 这实际上很有帮助。我一直试图用 remove_if 来做这件事,这告诉我问题出在哪里。谢谢。
      • @AdeMiller 我也是。 I hate remove_if.
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-21
      • 1970-01-01
      • 1970-01-01
      • 2014-06-28
      • 2018-05-28
      • 1970-01-01
      • 2020-02-01
      相关资源
      最近更新 更多