C++ 使用std::pair键映射,其中pair元素没有顺序重要性
正如问题所说,我需要以这样的方式使用std::mapC++ 使用std::pair键映射,其中pair元素没有顺序重要性,c++,stl,C++,Stl,正如问题所说,我需要以这样的方式使用std::map std::map<std::pair<int, int>, int*> m; int* a_ptr = new int; *a_ptr = 15; m[std::make_pair(1, 2)] = a_ptr; std::cout << *m[std::make_pair(2, 1)] << std::endl; //should output 15 std::map m; int*a_p
std::map<std::pair<int, int>, int*> m;
int* a_ptr = new int;
*a_ptr = 15;
m[std::make_pair(1, 2)] = a_ptr;
std::cout << *m[std::make_pair(2, 1)] << std::endl; //should output 15
std::map m;
int*a_ptr=新的int;
*a_ptr=15;
m[std::make_pair(1,2)]=a_ptr;
std::cout您能简单地确保这些对始终处于相同的顺序吗?使用辅助函数,如:
std::pair<int,int> my_make_pair(int a, int b)
{
if ( a < b ) return std::pair<int,int>(a,b);
else return std::pair<int,int>(b,a);
}
std::配对我的配对(INTA,INTB)
{
如果(a
并始终使用它访问地图:
m[my_make_pair(1,2)] = a_ptr;
std::cout << m[my_make_pair(2, 1)] << std::endl;
m[my_make_pair(1,2)]=a_ptr;
std::cout模板
结构对称对排序{
布尔运算符()(std::pair const&left,std::pair const&right)const{
如果(左。秒只需使用自定义比较器
[](std::pair<int, int> const& lhs, std::pair<int, int> const& rhs) {
int lhs_min = std::min(lhs.first, lhs.second);
int lhs_max = std::max(lhs.first, lhs.second);
int rhs_min = std::min(rhs.first, rhs.second);
int rhs_max = std::max(rhs.first, rhs.second);
return lhs_min < rhs_min || (!(rhs_min < lhs_min) && lhs_max < rhs_max)
}
[](标准::成对常数和左侧,标准::成对常数和右侧){
int lhs_min=std::min(lhs.first,lhs.second);
int lhs_max=std::max(lhs.first,lhs.second);
int rhs_min=std::min(rhs.first,rhs.second);
int rhs_max=std::max(rhs第一,rhs第二);
返回lhs_最小值
这是怎么回事?
前几行对一对中的2个元素进行了确定的排序;也就是说,您可以按任意顺序提供它们,lhs_min
&lhs_max
将是相同的。然后,我们对结果使用标准的等价技术。编译器将优化所有整数副本,并且min
/max
将为i在线
注意,为了便于键入,我使用了C++11的lambda,后来发现没有很好的方法将它们用作std::map
的比较器,因此您必须正确地编写一个函子。另一种解决方案是使用std::set
而不是std::pair
。集合按顺序存储数据,h因此,您无需订购这双鞋,因此可以精确地满足您的要求
另一方面,另一个答案是使用显式排序对的比较包装器(compare wrapper-around pair),这可能更实用。将映射包装在一个对对对元素进行排序的类中(因此p.first
)在将它们用作键之前?为什么要标记这个算法?@Knooth修复了这个问题。Yakk,我不敢相信我从来没有想到过它。@Tolga你也可以对指针进行异或运算,这个操作是可交换的,不会溢出。(但根据内存中对象的布局,它可能会有糟糕的哈希行为。)@millimoose这在我可以预见的其他一些情况下会派上用场。谢谢。怎么会这样?如果我有集合a,b
并在a中插入1,2,在b中以相反的顺序插入,那么a==b
是真的。是的,当然。它们有相同的内容。但是std::set
是一个有序结构;也就是说,它将其内容存储在一种有序的方式。是的,当然,正因为如此,它们满足了开箱即用的要求:这两个集合比较相等,因此{1,2}的查找也将匹配键{2,1}(注意,从数学上讲,它们只是相等).I被否决为std::set
是一个有序容器,这不是因为如果您以任意方式插入它们,它们不会比较相等(它们不会,它们比较相等)但是,std::map
s不关心它们的键是否相等。它们关心的只是严格的弱偏序,通常由std::less
和operator@Alex:好的,谢谢你的澄清,我更新了我的答案。我把集合的数学定义和集合的STL实现搞混了e、 事实上,我忽略了一个事实,即为了实现,必须存在一个排序(尽管这与它们在这里的使用无关)。你不能这样做。std::map
需要一个类型作为它的第三个模板参数,你给它一个lambda,这是一个值。要想在这里使用lambda作为比较器,你必须使用auto-cmp=[]…;typedef std::map mymap;
但您仍在创建一个无人使用的全局对象。首先可以使用一个函子。此外,我认为您指定的类型必须实现函数调用运算符()
?@snipes83不,lambda本质上是具有时髦构造函数和运算符()的函子
。这是一个很好的解决方案。在其他一些情况下,这会很方便,但是如果它不符合顺序,它会创建另一个pair对象,而Nate Hekman的将创建一个pair对象。我还没有太多可以访问map的地方,所以现在将make_对转换为my_make_对就可以了。否则这就是答案。-1我不喜欢否决一个pair对象我也回答了一些问题,但我不喜欢这里的递归调用;编译器是否能够删除它们并不明显。不幸的是,要使用自定义PairCmp,必须创建一个新的PairCmp,但为什么不直接将其传递给PairCmp
?4倍大小写看起来很难看。)它会更快,是的。我写了一个更快的,其中PairCmp
预计将采用std::pair
而不是'std::pair'。对于非平凡类型来说,这要难看得多,但可能更快:对于简单类型,我相信编译器可以在简单情况下找出递归。
[](std::pair<int, int> const& lhs, std::pair<int, int> const& rhs) {
int lhs_min = std::min(lhs.first, lhs.second);
int lhs_max = std::max(lhs.first, lhs.second);
int rhs_min = std::min(rhs.first, rhs.second);
int rhs_max = std::max(rhs.first, rhs.second);
return lhs_min < rhs_min || (!(rhs_min < lhs_min) && lhs_max < rhs_max)
}