[英]Map a range of values to a single value
I need to map values ranging between lowerBound
and upperBound
to a certain value. 我需要将介于
lowerBound
和upperBound
之间的值映射到某个值。
Illustrative Example: 说明性示例:
For example, imagine I have GPS system which has users subscribed to it. 例如,假设我有GPS系统,用户订阅了它。 This system is able to provide me the distance of the user from a certain point.
该系统能够为我提供用户与某一点的距离。 Based on the distance of the user I want to assign them an ID.
根据用户的距离,我想为他们分配一个ID。
Thus users in distance from 从而远离用户
1
to 100
get ID: 8.4
1
到100
获得ID: 8.4
101
to 200
get ID: 7.2
101
到200
获得ID: 7.2
201
to 300
get ID: 3.6
201
至300
获得ID: 3.6
401
to 600
get ID: 4.1
401
到600
获得ID: 4.1
and so on... 等等...
My approach: 我的方法:
So what I did, I created an std::map
by initializing it as follows: 所以我做了什么,我通过初始化它创建了一个
std::map
如下:
std::map<int, double> distanceToIdMap;
distanceToIdMap =
{
{100, 8.4},
{200, 7.2},
{300, 3.6},
};
Then I use this code to get the ID for the given distance: 然后我使用此代码获取给定距离的ID:
double roundUpToHundred = std::ceil(realDistance / 100.0) * 100;
double powerForDistance = distanceToIdMap.at(roundUpToHundred);
However my approach breaks down for the 401
to 600
distance, because by ceiling to the nearest hundred for a distance of 400+
I get the value 500
for which I don't have an entry in the map. 然而,我的方法分解为
401
到600
距离,因为天花板到最接近的百分之400+
距离我得到的值500
我没有在地图中的条目。 Of course the trivial solution would be to add an entry for 500
to the distanceToIdMap
but that is not how I want to handle this problem. 当然,简单的解决方案是在
distanceToIdMap
添加500
条目,但这不是我想要处理这个问题的方法。
I would like to have a map with {(lowerbound, upperbound) , correspondingID}
structure so I can address cases where an ID covers distance spanning more than 100m. 我希望有一个带
{(lowerbound, upperbound) , correspondingID}
ID {(lowerbound, upperbound) , correspondingID}
结构的地图,这样我就可以解决ID覆盖距离超过100米的情况。 And a given can check if the lowerBound
< realDistance
< upperBound
and then provide the ID. 并且给定的可以检查
lowerBound
< realDistance
< upperBound
然后提供ID。
It sounds like a use case for std::lower_bound . 它听起来像std :: lower_bound的用例。 Note that
lower_bound
is the correct implementation, not upper_bound
. 请注意,
lower_bound
是正确的实现,而不是upper_bound
。 This code compiles and works. 此代码编译和工作。 The
map
does not need to be sorted, as it is already sorted. map
不需要排序,因为它已经排序。 This should run in O(log(N)) . 这应该在O(log(N))中运行 。
You'll need to catch the exception... 你需要抓住异常......
#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;
}
Output: 输出:
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
Try upper_bound
: 尝试
upper_bound
:
auto upper = distanceToIdMap.upper_bound( 50 );
std::cout << "value:" << upper->second << std::endl;
http://www.cplusplus.com/reference/map/map/upper_bound/ http://www.cplusplus.com/reference/map/map/upper_bound/
with std::map::lower_bound
and boost::optional
, you may do something like: 使用
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;
}
}
What about avoiding maps at all? 那么避免使用地图呢?
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)) ;
Drawback: table must be properly ordered. 缺点:必须正确订购表格。
Here is a simple solution: 这是一个简单的解决方案:
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];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.