我有QMap<QString, myStruct>
myStruct {
QString firstname;
QString lastname;
QString status;
}
如何根据优先顺序对此QMap
进行排序:status
然后firstname
然后lastname
?
答案 0 :(得分:2)
据我了解,您希望检索以上述方式排序的地图值,但仍然可以访问该密钥。正确?
快速说来,地图是由键自动排序的<key, value>
对的集合,然后您可以尝试按值手动排序的<value, key>
对列表而不是。像QList<QPair<myStruct, QString>>
这样的内容,覆盖operator<
的{{1}}。
myStruct
当然,它是一次性使用结构,不会保持原始地图的更新,但你提到地图是固定的(常量?)所以它可能不是那么问题。
BTW,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>
,但我认为它更难阅读且可重复使用更少:
operator<
当然,您可以根据需要实现该比较lambda,我再次使用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
和lhs
会引用左侧和右侧在这种情况下,它们被排序算法用作rhs
,用于比较元素。
最后,如果你想避免lhs < rhs
,你必须手动进行比较(下面的代码修改了第一个版本的std::tie
):
operator<
答案 1 :(得分:1)
您无法手动对QMap
进行排序,您必须使用QList
(或QVector
)并使用std::sort
它。使用QMap::values()
将映射中的值(结构)提取到列表中,然后实现比较函数/方法并使用std::sort
调用它。有关如何执行此操作的一些提示,请参阅 cbuchart 的答案。
当值更改时保持地图和列表同步是一个不同的问题,如果这是一个要求,您应该创建一个单独的问题,添加MCVE以及您尝试的更多详细信息。