簡體   English   中英

std :: pair作為地圖中的鍵

[英]std::pair as key in map

我有一個大型圖像數據集,在特定時間拍攝,每個圖像捕獲start_timestop_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM