我遇到了一个我只能形容为完全不熟悉的问题,我可以寻求帮助。就上下文而言,我对 C++ 编程了解不多,我正在努力学习更多,因此我目前正在编写的代码比其他任何东西都更具教育意义。我想创建一个 unordered_map
,它包含一个字符串作为键和一个向量作为键的关联值。传统上,这将是微不足道的。但是,我的程序正在尝试将 json 数据解析为这个 unordered_map
数据结构,并且无法保证预先知道每个向量的类型。我唯一可以保证的是每个向量的类型将是以下类型集中的类型之一:string, int, double
。为了尝试实现以这种方式运行的 unordered_map,我尝试使用 variant
,但目前该变体实现导致超时错误。我希望得到一些关于超时原因的建议,最好是如何解决它。
代码如下(复制此问题的最小示例):
#include <nlohmann/json.hpp>
#include <unordered_map>
#include <variant>
#include <iostream>
#include <string>
using json = nlohmann::json;
int main() {
// map stores col name as string and vector with col type
std::unordered_map<std::string, std::vector<std::variant<double, long, std::string>>> mp;
// input is type nlohmann::json
json input = "{ \"happy\": \"yes\", \"pi\": 3.141, \"t\": 1608008400000 }"_json;
for(auto& el : input.items()) {
if (mp.find(el.key()) == mp.end()) {
std::cout << "trying insertion for key " << el.key() << std::endl;
mp.insert({ el.key(), std::vector<std::variant<double, long, std::string>>{ el.value() } });
std::cout << "inserted " << el.key() << " successfully!" << std::endl;
}
}
return 0;
}
这是我的输入(请注意,我的输入以 nlohmann::json 类型传递给此程序):
{"c":127.88,"h":127.9,"l":124.13,"n":867462,"o":124.34,"t":1608008400000,"v":157572262.0,"vw":126.5535},{"c":127.81,"h":128.37,"l":126.56,"n":550012,"o":127.41,"t":1608094800000,"v":95913591.0,"vw":127.5459}
这是当前的输出:
inserted c successfully!
trying insertion for key h
inserted h successfully!
trying insertion for key l
inserted l successfully!
trying insertion for key n
inserted n successfully!
trying insertion for key o
inserted o successfully!
trying insertion for key t
[1] 40305 killed ./test
我已尝试解决有关为什么会发生这种情况的一系列潜在不同问题,但我基本上已经通过反复试验确认,当我尝试将 std::variant<std::string, long, double>
用于我的向量类型时会出现此问题。当我为所有向量分配一个统一类型(例如,double
)时,所有插入都可以正常工作。然而,问题是可扩展性之一。尽管这个例子只包含双精度和长整数,但我希望将来能够解析一些看起来像这样的数据:
{"a": "test", "b": 1243.343, "c": 120910394023332}
没有错误并且返回值是(为了清楚起见显示了类型):
a : vector<string>{"test"}, b : vector<double>{1243.343}, c : vector<long>{120910394023332}
如果有什么我能澄清的可以帮助回答这个问题,请告诉我,我会添加进去。
答案 0 :(得分:2)
以下向量声明:
std::vector<int> v{4};
这将创建一个默认初始化为 4 个值的向量。这个重载的 std::vector
构造函数接受一个参数,该参数给出了向量的初始大小。
std::vector<std::variant<double, long, std::string>>{ el.value() } }
记住我的介绍,现在应该很明显这将调用相同的构造函数。
当我在调试器中逐步执行上述代码时,我的调试器揭示了这样一个事实:当 1608008400000 被传递到构造函数时,事情很快就变得松散了。我的计算机成功创建具有一万亿、六千八十亿、八百万和四十万值的向量的机会非常非常渺茫。
el.value()
不返回变体。它返回一个 JSON 值,并且没有现成的机制将其转换为变体。您必须自己完成所有工作,例如:
auto v=el.value();
if (v.is_number())
{
if (v.is_number_float())
{
vv.emplace_back( (double)v);
}
else
{
vv.emplace_back( (long)v);
}
}
else
{
vv.emplace_back( (std::string) v);
}
mp.insert({ el.key(), vv});
答案 1 :(得分:1)
我已经设法回答了我自己的问题(尽管是以迂回的方式)。我可以使用 is_number_integer()
中的 nlohmann::json
函数检查类型是否为整数。从那里,如果它是一个整数,我可以从中获取 uint64_t
值,然后将其插入到变体向量中。我必须进行的唯一修改是通过删除 long
并添加 uint64_t
来更改变体向量以更改可用类型。这是新代码:
int main() {
// map stores col name as string and vector with col type
std::unordered_map<std::string, std::vector<std::variant<double, uint64_t, std::string>>> mp;
// input is type nlohmann::json
// input.push_back(json::object_t::value_type("t", 1608008400000));
json input = "{ \"happy\": true, \"pi\": 3.141, \"t\": 1608008400000 }"_json;
for(auto& el : input.items()) {
if (mp.find(el.key()) == mp.end()) {
std::cout << "trying insertion for key " << el.key() << std::endl;
std::cout << "value is " << el.value() << " with type " << el.value().type_name() << std::endl;
if (el.value().is_number_integer()) {
mp.insert({ el.key(), std::vector<std::variant<double, uint64_t, std::string>>{ el.value().get<std::uint64_t>() } });
}
else {
mp.insert({ el.key(), std::vector<std::variant<double, uint64_t, std::string>>{ el.value() } });
}
std::cout << "inserted " << el.key() << " successfully!" << std::endl;
}
}
return 0;
}