如何使地图按值C++排序

How to make a map sort by value C++

本文关键字:C++ 排序 何使 地图      更新时间:2023-10-16

我试图使用自定义比较器按值对地图进行排序,但我无法弄清楚为什么我总是收到"没有匹配调用来比较ByVal"的错误

这是我的主要内容.cpp:

#include <map>
#include <iostream>
struct compareByVal {
bool operator[](const std::pair<int,int> & a, const std::pair<int,int> & b)
return a.second < b.second;
}
int main() {
std::map<int,int,compareByVal> hash;
hash[1] = 5;
hash[2] = 2;
hash[3] = 10;
std::cout << hash.begin()->first << std::endl;
}

第一个简单的问题是

struct compareByVal {
bool operator[](const std::pair<int,int> & a, const std::pair<int,int> & b)
return a.second < b.second;
}

应该是

struct compareByVal {
bool operator()(const std::pair<int,int> & a, const std::pair<int,int> & b) const {
return a.second < b.second;
}
};

第二个严重的问题是比较的签名是错误的。它应该是

struct compareByVal {
bool operator()(const int leftKey, const int rightKey) const;
}

无法访问比较函数中的值。没有(简单的(方法可以按值对地图进行排序。

简单地说,你不能。不确定你使用的是哪个编译器,但 clang 和 gcc 都提供了有用的消息。有上下文。

铛:static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},

海湾合作委员会:if (__i == end() || key_comp()(__k, (*__i).first))

您可以看到 clang 和 gcc 都只用它们的而不是值调用比较方法。这就是地图的工作方式。

如果要按值排序,则必须创建自己的自定义映射,或者更实际地使用值作为键。创建自己的地图来实现这一点比您想象的要困难得多,因为它必须在修改任何值后进行排序。

如果要按值对std::map进行排序,则使用了错误的容器。std::map按定义按键排序。

您可以包装键和值:

struct foo {
int key;
int value;
};

然后使用使用仅比较foo::value的比较器的std::set<foo>

首先,您收到错误的原因是:"没有匹配的调用来比较ByVal"是因为map的比较器仅适用于键。所以比较器应该喜欢:

struct compareByVal {
template <typename T>
bool operator()(const T& a, const T& b) const
return a < b;
}

谈到你想要实现的目标,我看到了两种方法:

  1. 将映射的所有元素复制到 std::vector 并对其进行排序:
std::vector<std::pair<int,int> > v(hash.begin(), hash.end());
std::sort(v.begin(), v.end(), [](const auto& a, const auto& b) { return a.second < b.second; });
  1. 将映射的所有元素复制到另一个映射,并将键作为值,值作为键。如果映射的值不是唯一的,则可以改用 std::multimap。

这可能是 X-Y 问题。

如果需要按键和值进行排序,则单个std::map可能不是最有效的选择。

在数据库理论中,所有数据都将放在一个表中。 将创建一个描述访问或排序方法的索引表。 需要在多个方法中排序的数据将具有多个索引表。

在C++,核心表将是一个std::vector。 索引是std::map<key1, vector_index>std::map<key2, vector_index>,其中vector_index是核心表中项目的索引。

例:

struct Record
{
int age;
std::string name;
};
// Core table
std::vector<Record> database;
// Index by age
std::map<int, unsigned int> age_index_table;
// Index by name
std::map<std::string, unsigned int> name_index_table;
// Fetching by age:
unsigned int database_index = age_index_table[42];
Record r = database[database_index];
// Fetching by name:
unsigned int database_index = name_index_table["Harry Potter"];
Record r = database[database_index];

您可以通过在互联网上搜索"数据库索引表 c++"来了解更多信息。

如果它看起来像一个数据库并且闻起来像一个数据库......