c++比较器函数,为映射指定特定的键顺序
C++ Comparator function to specifiy specific key ordering for map?
问题:如何编写一个函数来为映射构造函数创建一个键的特定顺序来做自定义比较器?
我有以下字符串键:
"a", "d", "i", "n", "ns", "ne", "vl", "rr"
我使用映射来为这些键写值。但是我需要它们按照上面所述的确切顺序进行排序。Map通常创建顺序:
a d i n ne ns rr vl
我如何编写一个比较器函数,我可以发送给映射构造函数,这样我就可以保持这个顺序?
这是我现在使用的
vector<pair<string, string>>({ { "a","" },{ "d","" },{ "i","" },{ "n","" },{ "ns","" },{ "ne","" },{ "vl","" },{ "rr","" }, { "","" } });
…然后我做了一系列的find_if调用。如果找到,我将值添加到pair中。如果没有,我就创建一个新的pair(在开始时)。我在开始时这样做,这样如果键不存在,我就可以返回"。好吧,除了我需要对上面没有列出的键进行排序之外,它都可以工作,因为任何键都可以添加。此外,当我试图添加一个不存在的密钥时,我的程序崩溃了。要调试一下……但是这样做是令人困惑的。使用带有一些特定排序的映射将完美地满足我的需求(运行时添加的任何键也应该通过默认比较进行排序,以保持顺序)。然而,这些"未知"(将来添加的)键可以排序。
我"想要这个"的原因(在注释中询问):我需要,在程序的最后一步,输出一个这样的字符串:
",a=legato,d=dn,i=12,n=A3"
等。它们需要以特定的顺序排列,因为我需要稍后使用regex(在单独的程序中)来操作这个字符串。顺序对于指定的键很重要。对于未指定的键,顺序也必须固定…
指定map用于排序键的比较器作为模板参数。所以你的map声明看起来像:
std::map<string, value_type, my_comparator> my_map;
比较器是您可以定义的东西,它接受两个key_type
参数a
和b
,然后如果a
在b
之前返回true(否则返回false)。一个这样的例子是:
struct my_comparator {
bool operator()(const string &a, const string &b) {
// Return true if a comes before b.
}
}
要实现您在问题中指定的排序,您可以按照以下行执行操作。我使用std::tuple
来确保满足严格的排序标准。
bool operator()(const string &a, const string &b) {
auto a_tuple = std::make_tuple(a == "a", a == "d", a == "i", ..., a);
auto b_tuple = std::make_tuple(b == "a", b == "d", a == "i", ..., a);
return a_tuple < b_tuple;
}
由于在元组的最后一个元素中有a
和b
,如果它不匹配您的预定义字符串之一,它将按这些进行排序。
查看对解释为什么需要这样做的问题的编辑,我建议使用默认排序的map
,然后在您想要输出值时咨询不同的列表:
std::vector<std::string> ordering = { "a", "d", "i", "n", "ns", "ne", "vl", "rr" };
for (const auto& key : ordering)
...output the_map[key]...
无论如何,如果您坚持使用不同顺序的map
,您可以根据需要进行特殊处理:
struct WeirdLess
{
bool operator<(const std:string& lhs, const std::string& rhs) const
{
if (lhs == "ne" && rhs == "ns" ||
lhs == "ns" && rhs == "ne" ||
lhs == "rr" && rhs == "vl ||
lhs == "vl" && rhs == "rr")
return rhs < lhs;
return lhs < rhs;
}
};
std::map<std::string, std::string, WeirdLess> my_map;
如果你最终在map
中有数百个条目,并且其中一半需要特殊的大小写,那么它不是很可扩展。试图想出一些逻辑来捕捉为什么特定的字符串更早出现——或者至少是一种识别它们的启发式方法——这可能是一个更好的主意。例如:
bool operator<(const std:string& lhs, const std::string& rhs) const
{
if (lhs.size() == 2 && rhs.size() == 2 && lhs[0] == rhs[0])
return rhs < lhs;
return lhs < rhs;
}
这是如何为map创建比较器函数来为一些键创建特定的排序顺序。
从其他答案中得到的灵感使我能够写出自己的答案,以尽可能准确和最好的方式解决我的问题(IMO)。
运行:https://ideone.com/7H5CZg
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
// create vector holding desired ordering
vector<string> order({ "a", "d", "i", "n", "ns", "ne", "vl", "rr" });
// create sort function for map
struct my_comparator {
bool operator()(const string &s1, const string &s2) {
// find() - it.begin() gives you the index number.
int a = find(order.begin(), order.end(), s1) - order.begin();
int b = find(order.begin(), order.end(), s2) - order.begin();
return a < b; // lower index < higher index
}
};
int main() {
// create the map
map<string,string, my_comparator> MyMap = { { "a","legato" }, { "i","3" }, { "vl","3" }, { "rr","2" } };
// output map
for (auto& it : MyMap) cout << it.first << "=" << it.second << " ";
return 0;
}
输出:a=legato i=3 vl=3 rr=2
UPDATE:这通常会更快,它使用map而不是vector来查找键顺序。
你也可以把这种方法应用到其他答案上。
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
// using a map is faster in most cases (with more keys and such)
map<string, int> maporder({ {"a", 1}, {"d", 2}, {"i", 3}, {"n", 4}, {"ns", 5}, {"ne", 6}, {"vl", 7}, {"rr", 8} });
// create sort function for map
struct mapcomp {
bool operator()(const string &s1, const string &s2) {
// compares ints by looking them up with the input string
return maporder[s1] < maporder[s2];
}
};
int main() {
// create the map
map<string,string, mapcomp> MyMap = { { "a","legato" }, { "i","3" }, { "vl","3" }, { "rr","2" } };
// output map
for (auto& it : MyMap) cout << it.first << "=" << it.second << " ";
return 0;
}
根据持有键的向量顺序对一对向量进行排序
这不是原来问题的答案,而是所描述的问题的解决方案。关于这个概念的更快版本,请参阅我的其他答案。
运行:https://ideone.com/8ICRwZ
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
// create vector holding desired ordering
vector<string> order({ "a", "d", "i", "n", "ns", "ne", "vl", "rr" });
// create sort function for vector of pairs
bool comparator(const pair<string, string> &s1, const pair<string, string> &s2) {
// find() - it.begin() gives you the index number.
int a = find(order.begin(), order.end(), s1.first) - order.begin();
int b = find(order.begin(), order.end(), s2.first) - order.begin();
return a < b; // lower index < higher index
};
int main() {
// create the map
map<string,string> MyMap = { { "a","legato" }, { "vl","3" }, {"i", "3"}, { "rr","2" } };
// convert map into vector of pairs
vector<pair<string,string>> vp;
for (auto& it : MyMap) vp.push_back({ it.first, it.second });
// sort the vector
sort(vp.begin(), vp.end(), comparator);
// put the vector pairs into a string format
for (auto& it : vp) cout << it.first << "=" << it.second << " ";
return 0;
}
输出:a=legato i=3 vl=3 rr=2
函数根据输入向量对集合进行排序
一个好朋友和伟大的程序员为我写了这个答案。根据ideone.com的说法,这是最有效的解决方案。这不是最初问题的答案,但它是实际问题的答案。
//first param is the container you want to sort
//second param is the container that holds the order of things
vector<pair<string,string>> KeySort(map<string,string> s, const vector<string>& order){
vector<pair<string,string>> res;
for (const auto& it : order) {
auto needle = s.find(it);
if (needle != s.end()) {
res.emplace_back(move(*needle));
s.erase(needle);
}
}
for (auto&& it : s) res.emplace_back(move(it));
return res;
}
ideone基准测试:https://ideone.com/GYsiM8
示例:https://ideone.com/eAU5US
// create vector holding desired ordering
vector<string> ord({ "a", "d", "i", "n", "ns", "ne", "vl", "rr" });
// create the map
map<string,string> MyMap = { {"a","legato"}, {"vl","4"},
{"i","2"}, {"rr","3"}, {"z","unspecified1"}, {"b","unspecified2"}};
// sort the vector
vector<pair<string,string>> out = KeySort(MyMap, ord);
output: a=legato i=2 vl=4 rr=3 b=unspecified2 z=unspecified1
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- CMake-按正确顺序将项目与C运行时对象文件链接
- C/C++ Windows 或 Linux 将随机内存块映射成连续的顺序
- C++静态初始化顺序:添加到映射中
- 创建按顺序索引的有序映射
- 多重映射是否保证广告顺序与其初始值设定项中给出的元素顺序匹配
- 以std::字符串作为关键字,按字典顺序对一个无序映射进行排序
- 映射的默认顺序
- 为什么继承顺序或映射会影响 vftable 的下标?(对于 VSC 表示C++)
- C++ 自定义映射键/值不按顺序排列
- C++学习映射输入的顺序
- 如何按插入顺序从映射中检索元素
- C++ 映射对象的顺序
- 是否可以按值顺序迭代映射
- c++比较器函数,为映射指定特定的键顺序
- iPhone TCP-IP字节顺序映射
- vc++中相等键的多映射顺序
- 按字符顺序将字符串从映射转换为二维矢量
- 如何在多映射中按排序顺序打印键的值
- 如何根据 c++ 中键的递增/减顺序打印哈希映射的值