【发布时间】:2012-10-18 06:09:45
【问题描述】:
我想创建一个包含复合键的映射。例如,我有学生的姓名和他/她正在学习的学期。现在我想创建一个地图,让卷号和学期一起作为地图的键。
【问题讨论】:
我想创建一个包含复合键的映射。例如,我有学生的姓名和他/她正在学习的学期。现在我想创建一个地图,让卷号和学期一起作为地图的键。
【问题讨论】:
编辑: 有一瞬间的疑问让我想知道 operator==() 是否也必须由键类型提供,因为显然在 map 中查找值时,必须进行相等性测试在引擎盖下使用。但是 2003 C++ 标准中的 23.1.2/3 表示没有必要:需要通过检查 a < b 和 b < a 是否为假来确定两个关键对象 a 和 b 之间的相等性。 :)
#include <map>
struct key {
int rollNo;
int semester;
string whateverElse;
// Provide a "<" operator that orders keys.
// The way it orders them doesn't matter, all that matters is that
// it orders them consistently.
bool operator<(key const& other) const {
if (rollNo < other.rollNo) return true; else
if (rollNo == other.rollNo) {
if (semester < other.semester) return true; else
if (semester == other.semester) {
if (whateverElse < other.whateverElse) return true;
}
}
return false;
}
};
std::map<key, whateverValueTypeYouWant> dictionary;
【讨论】:
if(a<b) return true; if(a>b) return false;,那么你就不需要嵌套ifs了。
if (b<a) return false; 用于第二部分,以便所有比较都通过operator<() 进行。
boost::tie(this->rollNo, this->semester, this->whateverElse) < boost::tie(other.rollNo, other.semester, other.whateverElse);,元组默认具有字典顺序;)
与其为键定义自己的类并且必须定义自己的比较运算符,因为您只关心卷号和学期,我会使用 std::pair。
#include <utility>
#include <map>
// This maps an std::pair of (roll number, semester) to a StudentRecord.
std::map<std::pair<int, int>, StudentRecord> studentMap;
studentMap.insert(std::pair<std::pair<int, int>, StudentRecord>(std::make_pair(100, 100), StudentRecord());
如果您对卷号和学期使用的不是 int 值,您可以轻松地使用这对中的值。请记住,如果您为这些对象使用自定义结构,它们将需要实现相等和比较运算符,在这种情况下,您将失去使用一对而不是直接使用其他结构的好处。
【讨论】:
T 和U 都可以通过< 进行比较,那么std::pair<T, U> 类型将自动通过< 进行比较,这是您最自动化的无论如何都可以希望:)
std::tuple
std::map 键需要实现 operator
#include <map>
struct Student
{
Student(int roll_no, int semestre)
: roll_no(roll_no), semestre(semestre)
{}
int roll_no;
int semestre;
bool operator< (Student const &s) const
{
return semestre* 100000+ roll_no< s.semestre* 100000+ s.roll_no;
}
};
#include <iostream>
#include <ostream>
int main()
{
std::map<Student, int> m;
m[Student(1, 1)]= 42;
m[Student(1, 2)]= 43;
std::cout<< m[Student(1, 1)];
}
【讨论】:
Student 成为映射类型,并使用 Student 数据作为单独的键。
semestre 乘以 100000 的效果是允许使用单个整数比较来完成比较。如果您确定 roll_no 永远不会超过 99999,这是一种方便的技术。
您可以定义一个包含 roll_no 和学期成员的结构类型。
struct stu_key
{
int roll_no;
int semester;
bool operator <(const stu_key &sk) const
{
//compare roll_no and semester
}
};
std::map<stu_key , value_type> stu_map;
【讨论】:
operator<() 需要标记为const,它的参数也是如此。
typedef 并将参数调用operator<() 简单地const stu_key &sk。您不需要 struct 关键字或 C++ 中的 typedef struct ... 解决方法。