如何排序QMap <qstring,mystruct =“”>?

时间:2017-10-16 07:55:01

标签: c++ qt sorting qsort qmap

我有QMap<QString, myStruct>

myStruct {
    QString firstname;
    QString lastname;
    QString status;
}

如何根据优先顺序对此QMap进行排序:status然后firstname然后lastname

2 个答案:

答案 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::tielhs会引用左侧右侧在这种情况下,它们被排序算法用作rhs,用于比较元素。

最后,如果你想避免lhs < rhs,你必须手动进行比较(下面的代码修改了第一个版本的std::tie):

operator<

答案 1 :(得分:1)

您无法手动对QMap进行排序,您必须使用QList(或QVector)并使用std::sort它。使用QMap::values()将映射中的值(结构)提取到列表中,然后实现比较函数/方法并使用std::sort调用它。有关如何执行此操作的一些提示,请参阅 cbuchart 的答案。

当值更改时保持地图和列表同步是一个不同的问题,如果这是一个要求,您应该创建一个单独的问题,添加MCVE以及您尝试的更多详细信息。