我需要将lowerBound
和upperBound
之间的值映射到某个值。
说明性示例:
例如,假设我有GPS系统,用户订阅了它。该系统能够为我提供用户与某一点的距离。根据用户的距离,我想为他们分配一个ID。
因此用户距离
1
至100
获取ID: 8.4
101
至200
获取ID: 7.2
201
至300
获取ID: 3.6
401
至600
获取ID: 4.1
依旧......
我的方法:
所以我做了什么,我通过如下初始化创建了std::map
:
std::map<int, double> distanceToIdMap;
distanceToIdMap =
{
{100, 8.4},
{200, 7.2},
{300, 3.6},
};
然后我使用此代码获取给定距离的ID:
double roundUpToHundred = std::ceil(realDistance / 100.0) * 100;
double powerForDistance = distanceToIdMap.at(roundUpToHundred);
然而,我的方法在401
到600
距离时出现故障,因为距离为400+
的天花板到最接近的100,我得到的值为500
我在地图上没有条目。当然,简单的解决方案是将500
的条目添加到distanceToIdMap
,但这不是我想要处理此问题的方式。
我希望有一个{(lowerbound, upperbound) , correspondingID}
结构的地图,以便我可以解决ID覆盖距离超过100米的情况。并且给定的可以检查lowerBound
&lt; realDistance
&lt; upperBound
然后提供ID。
答案 0 :(得分:4)
这听起来像std::lower_bound的用例。请注意,lower_bound
是正确的实现,而不是upper_bound
。此代码编译和工作。 map
不需要排序,因为它已经排序。这应该在 O(log(N))。
你需要抓住异常......
#include <iostream>
#include <algorithm>
#include <map>
#include <stdexcept>
using namespace std;
std::map<int, double> distanceToIdMap =
{
{100, 8.4},
{200, 7.2},
{300, 3.6},
{600, 4.1}
};
double Distance(int user)
{
auto x = std::lower_bound(distanceToIdMap.begin(), distanceToIdMap.end(), std::pair<const int,double>(user,0));
if (x == distanceToIdMap.end()) throw std::runtime_error("can't find");
return x->second;
}
int main()
{
for(int user=25;user < 650;user+=25)
{
cout << user << " " << Distance(user) << std::endl;
}
return 0;
}
输出:
sh-4.3# g++ -o main *.cpp -std=c++11
main
sh-4.3# main
25 8.4
50 8.4
75 8.4
100 8.4
125 7.2
150 7.2
175 7.2
200 7.2
225 3.6
250 3.6
275 3.6
300 3.6
325 4.1
350 4.1
375 4.1
400 4.1
425 4.1
450 4.1
475 4.1
500 4.1
525 4.1
550 4.1
575 4.1
600 4.1
terminate called after throwing an instance of 'std::runtime_error'
what(): can't find
Aborted (core dumped)
sh-4.3# main
答案 1 :(得分:2)
尝试upper_bound
:
auto upper = distanceToIdMap.upper_bound( 50 );
std::cout << "value:" << upper->second << std::endl;
答案 2 :(得分:2)
使用std::map::lower_bound
和boost::optional
,您可能会执行以下操作:
const std::map<int, boost::optional<double>> distanceToIdMap =
{
{0, boost::none},
{100, 8.4},
{200, 7.2},
{300, 3.6},
{400, boost::none},
{600, 4.1}
};
for (auto v : {-10, 50, 99, 100, 101, 250, 350, 500, 601})
{
auto it = distanceToIdMap.lower_bound(v);
if (it != distanceToIdMap.end() && it->second) {
std::cout << v << " " << *it->second << std::endl;
} else {
std::cout << v << " None" << std::endl;
}
}
答案 3 :(得分:1)
完全避免地图怎么样?
std::vector<std::pair<double, double>> table =
{
{0, 0},
{94.5, 2.1},
{314.4, 4.7}
} ;
double distance = ...
double value = std::upper_bound(table.begin(), table.end(), std::pair(distance, 0)) ;
缺点:必须正确订购表格。
答案 4 :(得分:0)
这是一个简单的解决方案:
int mapdistance[] = {100,200,300};
double mapid[] = {8.4,7.2,3.6};
double dist=0;
for(int i=0;i<sizeof(mapdistance)/sizeof(int);i++) {
dist += mapdistance[i];
if (realdistance<=dist) return mapid[i];
}