据我了解,您希望检索按上述方式排序的地图值,但仍可以访问该键。对吧?
快速地说,地图是由 key 自动排序的 <key, value> 对的集合,那么您可以尝试按 value 手动排序的 <value, key> 对列表反而。类似于QList<QPair<myStruct, QString>>,同时覆盖operator< 为myStruct。
struct myStruct {
QString firstname;
QString lastname;
QString status;
bool operator<(const myStruct& o) const {
return std::tie(status, firstname, lastname) <
std::tie(o.status, o.firstname, o.lastname);
}
};
QMap<QString, myStatus> map; // your original map
QList<QPair<myStatus, QString>> inv;
// Populate the inverted list
for (auto k : map.keys()) {
inv.append(QPair<myStatus, QString>(map[k], k));
}
std::sort(std::begin(inv), std::end(inv));
for (auto p : inv) {
qDebug() << p.first.status << p.first.firstname << p.first.lastname << p.second;
}
当然,它是一次性使用结构,不会与您的原始地图保持更新,但您提到地图是固定的(常量?)所以它可能不是那么问题来了。
顺便说一句,QMap 可用于反向查找,但仅在 myStruct 部分的值也是唯一的情况下(因此它们也可以用作键),否则您可能会覆盖构造逆映射时的值。
注意:std::tie 仅用于简化元组的排序条件(因此您需要包含 <tuple>)。
更新
回答您的一个 cmets:是的,您还可以指定自己的比较谓词,然后避免覆盖 operator<,但我认为它更难阅读且可重用性较低:
std::sort(std::begin(inv), std::end(inv),
[](const QPair<myStatus, QString>& lhs, const QPair<myStatus, QString>& rhs) {
return std::tie(lhs.first.status, lhs.first.firstname, lhs.first.lastname) <
std::tie(rhs.first.status, rhs.first.firstname, rhs.first.lastname);
});
当然,您可以根据需要实现该比较 lambda,我再次使用 std::tie 来简化帖子中的逻辑。不利的一面是,如果您需要在多个地方生成逆映射,则必须在各处重复 lambda 表达式(当然,也可以创建一个函数来创建逆映射)。
作为旁注,如果您好奇,lhs 和 rhs 分别指左侧和右侧,在此如果它们被排序算法用作lhs < rhs 来比较元素。
最后,如果您想避免std::tie,则必须手动进行比较(下面的代码修改了第一个版本的operator<):
bool operator<(const myStruct& o) const {
if (status < o.status) return true;
if (status > o.status) return false;
// status == o.status, move to next attribute
if (firstname < o.firstname) return true;
if (firstname > o.firstname) return false;
// firstname== o.firstname, move to next attribute
if (lastname < o.lastname) return true;
if (lastname > o.lastname) return false;
return false; // are equal
}