迭代 std::map 的更好方法

Better way to iterate std::map

本文关键字:更好 方法 map std 迭代      更新时间:2023-10-16

给定一个地图,我需要检索和操作两个立即存储的项目。对我来说,在矢量上工作更容易,因为我可以做"iter + 1"或"iter - 1"。而对于地图,我不走运。

例如,我举一个简单的例子如下:注意:在我的实际应用程序中,我不会简单地减去这些数字。

int main ()
{
    map<char,int> mymap;
    map<char,int>::iterator it;
    mymap['b'] = 100;
    mymap['a'] = 200;
    mymap['c'] = 300;
    // show content:
    map<char,int>::iterator firstItem  = mymap.begin();
    map<char,int>::iterator secondItem = ++mymap.begin();
    for ( ; secondItem != mymap.end(); ++firstItem, ++secondItem )
        cout << secondItem->second - firstItem->second << endl;
    return 0;
}

问题>有更好的解决方案吗?

谢谢

与其在循环控件中增加两个迭代器(增量有点慢),只需分配firstItem = secondItem然后递增secondItem即可。

您可以使用单个迭代器来完成此操作。将增量从标题移动到循环的中间,并在到达地图末尾时退出循环,如下所示:

map<char,int>::iterator item  = mymap.begin();
for (;;) {
    int first = item->second;
    ++item;
    if ( item == mymap.end()) break;
    cout << item->second - first << endl;
}

这是一个风格问题。你可以做例如。

auto first = m.begin();
if (first != m.end())
{
    auto second = first;
    second++;
    for (; second != m.end(); first = second++)
    {
        ...        
    }
}

地图为空的情况下,您也可以更优雅地救助。例如,您可以执行以下操作:

if (m.empty()) return;
auto first = m.begin(), second = first;
for (second++; second != m.end(); first = second++)
{
   ...
}

如果可以的话,我会喜欢后者,只有在必须的情况下才使用前者。

如果映射为空,则当前循环将显示未定义的行为

您的循环可以重写(更简单,并检查空映射),如下所示:

int main(int argc, char * argv[])
{
    map<char,int> mymap;
    map<char,int>::iterator it;
    mymap['b'] = 100;
    mymap['a'] = 200;
    mymap['c'] = 300;
    for ( it = ( mymap.begin() == mymap.end() ? mymap.end() : std::next(mymap.begin()) ) ; it != mymap.end(); ++it )
        cout << it->second - std::prev(it)->second << endl;
    return 0;
}

如果映射为空,您的代码将具有未定义的行为,但除此之外,这似乎是一种合理的方法,具体取决于您的总体目标。由于map迭代器不是随机访问,因此您不能只加减一个,只能递增/递减。

另一种方法是创建迭代器的副本,然后在循环内递增。

既不好也不差,只是一个替代方案:

if (map.size() >=2)
std::accumulate(
  ++mymap.begin(),
  mymap.end(),
  mymap.begin(),
  [](mymap_type::const_iterator iprev, mymap_type::value_type const& entry)->mymap_type::const_iterator
  { 
    /* do something */;
    return ++iprev; 
  });