std::map - 擦除最后一个元素

std::map - erase last element

本文关键字:最后一个 元素 擦除 map std      更新时间:2023-10-16

我的地图是这样定义的: map<string, LocationStruct> myLocations;,其中键是时间字符串

我只在这张地图中保留了 40 个项目,并且想在达到 40 个项目时放下地图中的最后一个项目。 我知道我做不到myLocations.erase(myLocations.end()),那我该怎么做呢?

我确实打算让地图中的最后一项是最古老的,因此是 FIFO。 数据会很快(大约20Hz),所以我希望地图能跟上它。我确实需要根据时间查找数据,所以我确实需要它成为关键,但我愿意接受完成此操作的替代方法。

字符串的格式是非常冗长的"6 月 21 日星期四 18:44:21:281",尽管为了简单起见,我可以将其缩减为自纪元以来的秒数。 这是我第一次尝试,还没有对格式考虑太多。

最惯用的方式是:

myLocations.erase( std::prev( myLocations.end() ) );

如果您没有 C++11,请使用您的相应函数工具箱。

试试这个,它有效:

map<string, LocationStruct>::iterator it = myLocations.end();
it--;
myLocations.erase(it);

我假设当你说"擦除最后一个元素"时,你的意思是"擦除最旧的元素"。

我不会使用字符串表示时间,而是使用日期/时间类型(如 unix 时间戳)。然后它们将按时间排序,而不是按字典顺序排序,您可以myLocations.erase(myLocations.begin()),因为最古老的总是在开头。

更好的是,使用boost::circular_buffer <std::pair<timetype, LocationStruct>>,并使用std::lower_bound按时间查找元素。 这将自动为您删除最旧的元素,并且在按时间查找元素时具有相同的徽标复杂性。 添加数据时速度也更快。 对于你的情况来说,这几乎是赢家。 如果你真的想避免boost,那么std::deque最适合你的需求,并提供出色的性能,但如果你已经有一个工作map,那么留在std::map可能是最好的。

以下是在deque中查找的方法:

typedef ???? timetype;
typedef std::pair<Timetype, LocationStruct> TimeLocPair
typedef std::deque<TimeLocPair> LocationContainer;
typedef LocationContainer::const_iterator LocationIterator;
bool compareTimeLocPair(const TimeLocPair& lhs, const TimeLocPair& rhs)
{return lhs.first < rhs.first;}
LocationIterator find(const LocationContainer& cont, timetype time) {
    TimeLocPair finder(time, LocationStruct());
    LocationIterator it = std::lower_bound(cont.begin(), cont.end(), finder, compareTimeLocPair);
    if (it == cont.end() || it->first != time)
        return cont.end();
    return it;
}

好吧,对 g++ 4.4 的快速检查表明这工作得很好:

myLocations.erase(myLocations.rbegin()->first);

虽然我必须承认我不知道为什么它不喜欢只接受迭代器本身。

由于您将时间存储为键字符串。最后一个元素(考虑到从 00:00 到 24:00 的时间,一天中最早的时间)将是一个下界元素,因此您可以像这样获取迭代器

     `map<string, LocationStruct>::iterator it;`
      it=myLocations.lower_bound ('00:00');
      myLocations.erase ( it, it+1);

但是if it belongs to different dates,您甚至需要考虑这一天并相应地编写代码。正如您data is coming quick enough提到的,您无需考虑日期。但是The safe way here would be take the entire date in terms of second and remove the lowest one as mentioned above.即使新数据到达的频率非常慢,也会小心。

对于没有 TS 绑定的最后一个元素map::erase,只需使用以下元素:

myLocations.erase ((--myLocations.end()));