如何在全球范围内定义unordered_map?

How to define an unordered_map at global level?

提问人:Ξένη Γήινος 提问时间:8/11/2023 最后编辑:Ξένη Γήινος 更新时间:8/11/2023 访问量:155

问:

我正在尝试在全局级别定义两个无序映射,我用循环定义它们,我不想将循环放在 .main()

更具体地说,我正在尝试定义一个以 36 为基数的字母表,我使用阿拉伯数字表示数字 0-9,然后使用基本拉丁字母表示数字 10-35,一个映射用于将字符串转换为整数,它应该支持大写和小写,另一个用于将整数转换为给定基数中的字符串表示形式,并且它应该只是小写。

这是我的代码,显然它不起作用:

#include <unordered_map>

using namespace std;
const unordered_map<string, int> digits;
const unordered_map<int, string> alphabet;

for (int i = 0; i < 10; i++) {
    string d = char(i + 48);
    digits[d] = i;
    alphabet[i] = d;
}

for (int i = 10; i < 36; i++) {
    string upper = char(i + 55);
    string lower = char(i + 87);
    digits[upper] = i;
    digits[lower] = i;
    alphabet[i] = lower;
}

我知道如果我将循环放在函数中,它应该可以工作。但我不想那样做。main()

有没有办法直接初始化它们,并使用赋值运算符来定义它们,可能带有理解力?

类似于以下 Python 代码:

DIGITS = {
    **{chr(i + 48): i for i in range(10)},
    **{chr(i + j): i for i in range(10, 36) for j in (55, 87)},
}

ALPHABET = {
    **{i: chr(i + 48) for i in range(10)},
    **{i: chr(i + 87) for i in range(10, 36)},
}

有点无关紧要,但这是我当前的工作程序,它将字符串转换为数字,反之亦然,我试图摆脱转换函数中的 if 语句。

我想在这里熟悉它,并将其与 Python 的 .unordered_mapdict

C++ 全局变量 C++20 无序映射

评论

1赞 Pepijn Kramer 8/11/2023
一般来说,我会说不是。大型项目中的全局变量处理起来很痛苦。但在本例中,您可以将初始化代码移动到将返回初始化映射的 lambda 表达式。
0赞 Some programmer dude 8/11/2023
你想做的事情,使用循环和计算,初始化变量,必须在函数中完成。或者创建一个类或结构来解决问题,并使用其构造函数进行初始化。main
1赞 Some programmer dude 8/11/2023
另一方面,请不要以你的方式使用幻数。如果要循环使用这些值。然后减去得到实际的整数值。我建议你做一个从字符到整数值的映射。考虑到将数字字符转换为其整数值或相反值所需的简单算术,地图真正需要的是什么?这些地图的用例是什么?这些地图应该解决的实际问题是什么?'0''9''0'digit
0赞 Some programmer dude 8/11/2023
哦,数字的简单算术仅由数字的 C++ 规范保证。不能保证您的大写/小写字母在任何地方都有效。
0赞 ALX23z 8/11/2023
您使用无序映射将字符转换为数字,反之亦然?只需编写一个带有几个 if 的简单函数 - 它会更有效率。最大使用 a 来替换几个 if。std::stringstd::array

答:

9赞 Pepijn Kramer 8/11/2023 #1

使用直接调用的 lambda 表达式初始化变量。


#include <unordered_map>
#include <string>
#include <iostream>

// using namespace std; <== do not do this
const auto digits = [] 
{
    std::unordered_map<std::string, int> digits;
    for (int i = 0; i < 10; i++)
    {
        digits.insert({ std::to_string(i), i });
    }
    return digits;
}(); // make a lambda expression and immediately invoke it.

int main()
{
    // use a range-based for loop + structured binding
    // to show content of the map
    for (const auto& [key, value] : digits)
    {
        std::cout << "[" << key << ", " << value << "]\n";
    }
    return 0;
}

评论

0赞 ALX23z 8/11/2023
他也可以写一个函数而不是 lambda。同样的事情。
0赞 Pepijn Kramer 8/11/2023
@ALX23z 可能,但该函数也可以在其余代码中使用(这样它只能用于初始化)。这对于 constexpr 初始化(这超出了当前问题的范围)也非常有用。