[英]C++ map using pair as key
I am using a map (which seemed the best implementation after a previous question , with a pair key, as a 'container' for incoming messages that can be sorted according to sourceID and priority ie key: (sourceID, priority) which points to an int value. Processing will happen 'on' this map. 我正在使用一个地图(这似乎是上一个问题之后的最佳实现,带有一对密钥,作为传入消息的'容器',可以根据sourceID和优先级进行排序,即密钥:(sourceID,priority)指向一个int value。处理将在此地图上“发生”。
I've just come against a problem - I need to do something like this pseudo code to subsequently retrieve messages: 我刚刚遇到一个问题 - 我需要做一些像这样的伪代码来随后检索消息:
map<pair<int, int>, int> mymap;
if (!mymap[make_pair(nodeID,i)].empty()) //i refers to all the priority levels
//processing occurs here to retrieve a value
but I can't seem to do it easily. 但我似乎无法轻易做到。 Is there a way to do this simply without running an iterator eg for (i = 0; i <priority ; i++)
? 有没有办法在不运行迭代器的情况下执行此操作,例如for (i = 0; i <priority ; i++)
? I know that if I used an equivalent vector<vector<int>>
I would be able to do this easily, but a map works better for my program at the moment. 我知道,如果我使用等效的vector<vector<int>>
我可以很容易地做到这一点,但是地图对我的程序来说效果更好。
edit: 编辑:
The messages are sorted into the map by (sourceID, priority level), and then processed before being mapped into another map by (destID, priority level). 消息按(sourceID,优先级)排序到映射中,然后在通过(destID,优先级)映射到另一个映射之前进行处理。 I need to check there there are messages available for any particular destID, regardless of priority level, so I am looking for an easy way to check this. 我需要检查那里有可用于任何特定destID的消息,无论优先级如何,所以我正在寻找一种简单的方法来检查这一点。
I know that if I use a vector<vector<int>>
, I will be able to do something like node[2].empty()
, if I want to check that node 2 has no available messages. 我知道如果我使用vector<vector<int>>
,我将能够执行类似node[2].empty()
,如果我想检查节点2没有可用的消息。 Is there an equivalent for maps? 地图有等价物吗?
If I understand things correctly, you'd like a convenient way to determine how many entries (node_id,i)
the map has, where node_id
is fixed and i
can be anything. 如果我理解正确,你想要一个方便的方法来确定地图有多少条目(node_id,i)
,其中node_id
是固定的, i
可以是任何东西。
If this understanding is correct, you can make use of the fact that the ordering inside your map is based on the ordering defined by std::less<std::pair<int,int>>
, which by default is the lexicographical ordering. 如果这种理解是正确的,你可以利用这样一个事实,即你的地图中的排序是基于std::less<std::pair<int,int>>
定义的排序,默认情况下是字典排序。 In other words, the node-id will be used as the main sorting criterion, whereas the second element of the pair will be used as secondary sorting criterion. 换句话说,node-id将用作主要排序标准,而该对的第二个元素将用作次要排序标准。
You can therefore use the lower_bound
and upper_bound
functions of the map to determine the range of entries for a given node-id as follows (C++11 code, but can be converted to C++03): 因此,您可以使用map的lower_bound
和upper_bound
函数来确定给定node-id的条目范围,如下所示(C ++ 11代码,但可以转换为C ++ 03):
std::ptrdiff_t num_per_node(const mymap &map, const int node_id)
{
using std::distance;
static constexpr int min = std::numeric_limits<int>::min();
static constexpr int max = std::numeric_limits<int>::max();
auto lo = map.lower_bound({node_id,min});
auto hi = map.upper_bound({node_id,max});
return distance(lo,hi);
}
The function defined above returns the number of entries there are in the map map
for the given node-id node_id
. 上面定义的函数返回给定node-id node_id
的映射map
的条目数。
So your pseudo-code becomes: 所以你的伪代码变成:
if (num_per_node(mymap,nodeID) > 0)
The function has logarithmic complexity, which is clearly (asymptotically) better than iterating through all priority values. 该函数具有对数复杂度,这明显(渐近)比迭代所有优先级值更好。
Note that this only works because the elements of your pairs are int
, so it is readily possible to establish minimum and maximum values. 请注意,这只能起作用,因为对的元素是int
,因此很容易建立最小值和最大值。 Again, it also only works because of the lexicographical ordering. 同样,它也只能起作用,因为词典排序。 If you use a customised comparator function with your map, this method will no longer work, and whether a corrsponding method can be found depends on how exactly your comparator is defined. 如果对地图使用自定义比较器功能,则此方法将不再起作用,是否可以找到相应方法取决于比较器的确切定义。
Here is a GIT-gist with a complete example that demonstrates how the function can be used: https://gist.github.com/jogojapan/5027365 这是一个GIT-gist,其中有一个完整的示例,演示了如何使用该函数: https : //gist.github.com/jogojapan/5027365
Just to build on what @jogojapan has done, I've adapted it to not use C++11 (because I'm not using it), and leaving it here for reference. 仅仅基于@jogojapan所做的事情,我已经将其改编为不使用C ++ 11(因为我没有使用它),并将其留在这里作为参考。 Not sure it does everything his does, but works sufficiently for me 不确定它做了他所做的一切 ,但对我来说足够有效
#include <iostream>
#include <utility>
#include <limits>
#include <map>
using namespace std;
std::ptrdiff_t num_per_node(const map<pair<int, int>, int> &map, const int node_id)
{
using std::distance;
static int min = std::numeric_limits<int>::min();
static int max = std::numeric_limits<int>::max();
auto lo = map.lower_bound(make_pair(node_id,min));
auto hi = map.upper_bound(make_pair(node_id,max));
return distance(lo,hi);
}
int main() {
map<pair<int, int>, int> m;
m.insert(make_pair(make_pair(1,3),1));
m.insert(make_pair(make_pair(3,4),2));
m.insert(make_pair(make_pair(3,5),3));
m.insert(make_pair(make_pair(3,9),4));
m.insert(make_pair(make_pair(4,2),5));
m.insert(make_pair(make_pair(4,3),6));
m.insert(make_pair(make_pair(5,1),7));
m.insert(make_pair(make_pair(8,2),8));
for (int node_id = 0 ; node_id < 10 ; ++node_id)
std::cout << "node-id " << node_id << ": " << num_per_node(m,node_id) << '\n';
return 0;
}
which correctly returns 哪个正确返回
node-id 0: 0
node-id 1: 1
node-id 2: 0
node-id 3: 3
node-id 4: 2
node-id 5: 1
node-id 6: 0
node-id 7: 0
node-id 8: 1
node-id 9: 0
One of the possible solution could be using 2 nested maps: 其中一个可能的解决方案是使用2个嵌套映射:
typedef std::map<int,int> priorities;
typedef std::map<int,priorities> messages;
Find if there is any message for given sourceId and any priority becomes trivial for price of 2 lookups when you need to find message with given sopurceId and priority. 查找给定sourceId是否有任何消息,当您需要查找具有给定sopurceId和优先级的消息时,任何优先级对于2次查找的价格变得微不足道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.