简体   繁体   English

将一系列值映射到单个值

[英]Map a range of values to a single value

I need to map values ranging between lowerBound and upperBound to a certain value. 我需要将介于lowerBoundupperBound之间的值映射到某个值。

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 1100获得ID: 8.4
  • 101 to 200 get ID: 7.2 101200获得ID: 7.2
  • 201 to 300 get ID: 3.6 201300获得ID: 3.6
  • 401 to 600 get ID: 4.1 401600获得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. 然而,我的方法分解为401600距离,因为天花板到最接近的百分之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_boundboost::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;
    }
}

Live example 实例

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM