繁体   English   中英

如何排序QMap <QString, myStruct> ?

[英]How to sort QMap<QString, myStruct>?

我有一个QMap<QString, myStruct>

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

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

据我所知,你想检索以上述方式排序的地图值,但仍然可以访问密钥。 对?

快说,地图是一个集<key, value>对通过自动排序,那么你可以尝试的列表<value, key>对通过价值人工分拣代替。 类似于QList<QPair<myStruct, QString>> ,同时覆盖operator< for 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> )。

UPDATE

回答你的一条评论:是的,你也可以指定你自己的比较谓词,然后避免覆盖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表达式(或者创建一个函数来创建逆映射)。

作为旁注,如果你好奇, lhsrhs左手侧右手侧 ,在这种情况下,它们被排序算法用作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
}

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM