[英]std::pair as key in map
我有一个大型图像数据集,在特定时间拍摄,每个图像捕获start_time
和stop_time
都已知并编码为双精度。 我想根据模拟时间将每个连续图像加载到我的模拟中,即 - 检查当前模拟时间是否在开始/停止间隔内。
我想为此使用一个映射,其中键是std::pair<double, double>
的开始和停止时间,值是图像的完整路径。
std::map<std::pair<double, double>, std::string> _sequence; // t1, t2 and full path
我的问题:如何搜索这样的地图以查找_currentTime是否在区间对中?
首先,如果搜索包含是您想要做的主要事情,请不要使用键入std::pair<double, double>
的map
。 这不是一个对数据结构有意义的操作。
但是,如果你坚持,代码看起来像这样(在C ++ 11中):
bool isWithinInterval() const {
for (const auto& pr : _sequence) {
if (_currentTime >= pr.first.first && _currentTime <= pr.first.second) {
return true;
}
}
return false;
}
Pre-C ++ 11,同样的想法,只是略有不同的循环语法。 理想情况下,我们使用std::find_if
,但表达地图的value_type
是一件麻烦事。 但是在C ++ 14中,没有这样的麻烦:
auto it = std::find_if(_sequence.begin(),
_sequence.end(),
[_currentTime](const auto& pr) {
return _currentTime >= pr.first.first && _currentTime <= pr.first.second;
});
return it != _sequence.end();
要不就:
return std::any_of(_sequence.begin(), _sequence.end(),
[_currentTime](const auto& pr) {
return _currentTime >= pr.first.first && _currentTime <= pr.first.second;
});
一种方法可能是不使用std::map<std::pair<double, double>, std::string>
而是使用std::map<double, std::pair<double, std::string>>
:您将使用m.lower_bound(current_time)
来查找current_time
可以适合的元素范围的开头。 然后你走迭代器直到它到达终点,落入相关范围,或超出结束时间:
auto it = _sequence.lower_bound(current_time);
for (; it != _sequence.end() && current_time <= it->second; ++it) {
if (it.first <= current_time) {
// found a matching element at it
}
}
使用带有std::pair<double, double>
的布局std::pair<double, double>
一个键需要第二次出现。 但是,您可以使用std::make_pair(current_time, current_time)
。
double search = 0.; /* or some other value */
bool found = false;
for ( auto & key_value_pair : _sequence ) {
// key_value_pair.first == map key
// key_value_pair.second == key's associated value
if ( key_value_pair.first.first <= search || search <= key_value_pair.first.second ) {
found = true;
break;
}
}
if ( found ) {
/* it's within an interval pair! */
} else {
/* it's not within an interval pair! */
}
我建议也考虑一下boost::icl
如果可能,请不要使用std :: pair作为密钥。 它作为一个键并不真正有意义,因为最终会出现两个重叠范围映射到同一元素的情况。
无论如何,这是我如何实现这样一个问题的解决方案。 lower_bound
/ upper_bound
是你的朋友。 此外,您可以通过在停止时间键入值来避免反向迭代器技巧。
#include <map>
#include <stdio.h>
struct ImageStuff
{
double startTime;
double stopTime;
char data[1000];
};
typedef std::map<double, ImageStuff> starttime_map_type;
starttime_map_type starttime_map;
ImageStuff & MakeImage (double start, double stop) {
ImageStuff newImage;
newImage.startTime = start;
newImage.stopTime = stop;
return starttime_map[start] = newImage;
}
starttime_map_type::iterator FindByTime (double time) {
starttime_map_type::reverse_iterator i = starttime_map_type::reverse_iterator(starttime_map.upper_bound(time));
if (i == starttime_map.rend() || time > i->second.stopTime) {
printf ("Didn't find an image for time %f\n", time);
return starttime_map.end();
}
else {
printf ("Found an image for time %f\n", time);
return i.base();
}
return starttime_map.end();
}
int main (void)
{
MakeImage (4.5, 6.5);
MakeImage (8.0, 12);
MakeImage (1, 1.2);
auto i = FindByTime(3);
i = FindByTime(4.5);
i = FindByTime(9);
i = FindByTime(15);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.