std :: pair作为地图中的键

时间:2015-01-06 22:01:46

标签: c++ search intervals stdmap

我有一个大型图像数据集,在每个图像捕获start_timestop_time已知并编码为双精度的特定时间拍摄。 我想根据模拟时间将每个连续图像加载到我的模拟中,即 - 检查当前模拟时间是否在开始/停止间隔内。

我想为此使用地图,其中键是std::pair<double, double>的开始&amp;停止时间,值是图像的完整路径。

std::map<std::pair<double, double>, std::string> _sequence; // t1, t2 and full path

我的问题: 如何搜索这样的地图以查找_currentTime是否在区间对内?

4 个答案:

答案 0 :(得分:2)

首先,如果要搜索包含是您想要做的主要事情,请不要使用map键入std::pair<double, double>。这不是一个对数据结构有意义的操作。

但是如果你坚持,代码看起来就像这样(在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;
                   });

答案 1 :(得分:2)

一种方法可能使用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::make_pair(current_time, current_time)

答案 2 :(得分:0)

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

答案 3 :(得分:0)

如果可能,请不要使用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;
}