我的地图定义如下:
map<string, LocationStruct> myLocations;
其中键是时间字符串
我只保留此地图中的40个项目,并且当我达到40个项目时,我想放弃地图中的最后一个项目。我知道我不能做myLocations.erase(myLocations.end())
,所以我该怎么做呢?
我打算让地图中的最后一项成为最早的项目,因此也是FIFO。数据会很快(大约20Hz)进来,所以我希望地图可以跟上它。我确实需要根据时间查找数据,所以我确实需要它作为关键,但我愿意采用其他方法来实现这一目标。
字符串的格式是一个非常详细的“星期六6月21日18:44:21:281”,尽管我可以把它简化为简单时代以来的秒数。这是我的第一次尝试,并没有过多考虑这种格式。
答案 0 :(得分:11)
最惯用的方式是:
myLocations.erase( std::prev( myLocations.end() ) );
如果您没有C ++ 11,请使用您的相应功能 工具箱。
答案 1 :(得分:6)
我假设当你说“擦除最后一个元素”时,你的意思是“擦除最旧的元素”。
我不会多次使用字符串,而是使用日期/时间类型(如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;
}
答案 2 :(得分:6)
试试这个,它有效:
map<string, LocationStruct>::iterator it = myLocations.end();
it--;
myLocations.erase(it);
答案 3 :(得分:1)
嗯,快速检查g ++ 4.4表明这很好用:
myLocations.erase(myLocations.rbegin()->first);
虽然我必须承认我不知道为什么它不喜欢只接受迭代器本身。
答案 4 :(得分:0)
因为您将时间存储为键字符串。最后一个元素(考虑从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
。即使新数据到达的频率非常慢,这也会很谨慎。
答案 5 :(得分:0)
map::erase
对于没有TS绑定的最后一个元素,只需使用以下内容:
myLocations.erase ((--myLocations.end()));