如何过滤std :: map中的项目?

180*_*ION 27 c++ boost stl

我大致有以下代码.这可以更好或更有效吗?也许用std::remove_if?您可以在遍历地图时从地图中删除项目吗?我们可以避免使用临时地图吗?

typedef std::map<Action, What> Actions;
static Actions _actions;

bool expired(const Actions::value_type &action)
{
  return <something>;
}

void bar(const Actions::value_type &action)
{
  // do some stuff
}

void foo()
{
  // loop the actions finding expired items
  Actions actions;
  BOOST_FOREACH(Actions::value_type &action, _actions)
  {
    if (expired(action))
      bar(action);
    else
      actions[action.first]=action.second;
    }
  }
  actions.swap(_actions);
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ork 53

Mark Ransom算法的一种变体,但不需要临时的.

for(Actions::iterator it = _actions.begin();it != _actions.end();)
{
    if (expired(*it))
    {
        bar(*it);
        _actions.erase(it++);  // Note the post increment here.
                               // This increments 'it' and returns a copy of
                               // the original 'it' to be used by erase()
    }
    else
    {
        ++it;  // Use Pre-Increment here as it is more effecient
               // Because no copy of it is required.
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 做得很好.太糟糕了我花了2年半的时间才看到这个改进. (3认同)

Mar*_*som 30

你可以使用erase(),但我不知道BOOST_FOREACH将如何处理无效的迭代器.map :: erase文档说明只有擦除的迭代器才会失效,其他的应该没问题.这是我如何重构内循环:

Actions::iterator it = _actions.begin();
while (it != _actions.end())
{
  if (expired(*it))
  {
    bar(*it);
    Actions::iterator toerase = it;
    ++it;
    _actions.erase(toerase);
  }
  else
    ++it;
}
Run Code Online (Sandbox Code Playgroud)


cop*_*pro 5

似乎没有人知道的一件事是,当在任何容器上使用时,擦除都会返回一个新的、保证有效的迭代器。

Actions::iterator it = _actions.begin();
while (it != _actions.end())
{
  if (expired(*it))
  {
    bar(*it);
    it = _actions::erase(it);
  }
  else
    ++it;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,存储 actions.end() 可能不是一个好的计划,因为我相信迭代器的稳定性无法得到保证。

  • 随着 C++11 的出现,这个答案现在是正确的。+1 (4认同)
  • 看起来 map::erase() 也必须返回迭代器:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2728.html#130 (2认同)