python - 如何在 C++ 中高效地创建和编译大 map

标签 python c++ json enums maps

目前,我有多个 json 文件和一个 python 代码,它读取其中一个 json 文件 main.json,并根据 json 文件创建完整的 c++ 代码。在该 c++ 的 main() 中,我需要使用 numberToString.json 将数字输出转换为字符串。我找不到及时(<1 分钟)成功编译 c++ 代码的方法

我在 C++ 文件中创建了一个嵌套映射“std::map< std::string, std::map< std::string, std::string>> enumMap”,并填充了 numberToString.json 中的所有值(~20,000 个值),但代码没有及时编译(我在~5 分钟后将其关闭。CMAKE 使用 gcc 4.8.5 进行编译。)

示例代码:

main.json
    {"example" : {
       "FRUIT" : "ex_fruit"
    }, 
    ...
    }}
numberToString.json
    {"FRUIT" : {
       "1" : "fresh",
       ...,
       "10" : "not fresh"
    },
    ...
    }}
someHeader.h
    typedef struct FRUIT
    {
       int     val;
    };

    typedef struct Example
    {
       FRUIT   ex_fruit;
    };
python.py
    def someFunc(typename) 
    //input is struct name in string ex."Example"
       "already implemented"
       return memberVariables
       //returns member variable accessors

    print "#include \"someHeader.h\""
    print "int main() {"
    print "   Example ex = {1};"
    print "   printf(%s, %s);" %("%s", someFunc("Example")
    print "return 0;"
    print "}"
pythonOutput.cxx
    #include "someHeader.h"
    int main() {
       Example ex = {1};
       printf(%s, ***ex.ex_fruit.val***);
       return 0;
    }

因此在 pythonOutput.cxx 上,我需要 ex.ex_fruit.val,即 1,以“新鲜” 通过使用 numberToString.json。

我使用的是python 2.7

最佳答案

您绝对不应该自动生成像那样硬编码 map 的 C++ 代码。有一些库可以将 json 文件直接读入 C++(例如参见 rapid json),应该改用这些库。代码的编译速度会快得多,读取 20,000 个文件所需的时间应该在几毫秒的数量级(而不是编译所需的 >5 分钟)。

如果您想避免在 C++ 代码中添加对 json 解析器的依赖,我建议将 JSON 文件转换为更简单的格式,这样更易​​于使用 C++ 读取。

从文件中读取和写入 map 的非常非常简单的格式

让我们来一张简单的 map :

map<string, map<string, string>> test_map {
    {"Hello", {
        {"A", "B"}, 
        {"C", "D"}}},
    {"World", {
        {"Blarg", "glug glug glug"}, 
        {"idek what to put here", "felt cute might delete later"}}}}; 

我们将使用非常简单的格式将其写入文件。字符串将写为 <string length> <string text> , map 将写为 <map length> <map key-value pairs> .因此,例如 "Hello world"会写成 11 Hello world .对于上面的 map ,对应的文件是

2 5 Hello2 1 A1 B1 C1 D5 World2 5 Blarg14 glug glug glug21 idek what to put here28 felt cute might delete later

你有 2,这意味着顶级 map 有 2 个元素。后面跟着一个 5,这意味着第一个键中有 5 个字符。接下来是第一个映射的键和值等。

以这种格式将映射写入文件

因为格式很简单,所以做起来也很简单。

namespace output {
    using std::map; 
    using std::string; 
    void write(FILE* file, string const& str) {
        // Write the length of the string, followed by a space
        fprintf(file, "%lu ", str.size());

        // Write the string itself
        fwrite(str.data(), 1, str.size(), file);  
    }

    template<class Key, class Value>
    void write(FILE* file, map<Key, Value> const& m) {
        // Write the length of the map, followed by a space
        fprintf(file, "%lu ", m.size()); 

        for(auto& entry : m) {
            // Write the key
            write(file, entry.first);

            // Write the value
            write(file, entry.second); 
        }
    }
}

从文件中读取 map

这也很简单。例如,要读取一个字符串,我们读取长度,然后读取所有字符。

namespace input {
    using std::map;
    using std::string; 

    void read(FILE* file, size_t& length) {
        int result = fscanf(file, "%lu ", &length);
        if(result < 0) throw std::logic_error("Couldn't read from file"); 
    }

    void read(FILE* file, string& str) {

        size_t length;      // Read the length
        read(file, length); 

        str.resize(length); 
        size_t n_read = fread(&str[0], 1, length, file); // Read the characters

        if(n_read != length) { // Handle errors
            throw std::logic_error("Unable to read entirety of string from file"); 
        }
    }

    template<class Key, class Value>
    void read(FILE* file, map<Key, Value>& text) {
        size_t length;      // Read the length of the map
        read(file, length); 
        text.clear(); 

        for(size_t i = 0; i < length; i++) {
            Key key;
            read(file, key);        // Read the key
            read(file, text[key]);  // Read the value
        }
    }
}

使用这段代码

写 map :

void write_map(string file, map<string, map<string, string>> test_map) {
    auto output_file = fopen(file.c_str(), "w"); 
    output::write(output_file, test_map); 
    fclose(output_file); 
}

阅读 map :

map<string, map<string, string>> read_map(string file) {
    auto input_file = fopen(file.c_str(), "r"); 
    map<string, map<string, string>> m;
    input::read(file, m); 
    fclose(input_file); 
    return m; 
}

测试这段代码

You can see a live demonstration here

这个主要功能会将测试 map 写入文件,然后将其读回不同的 map ,然后比较两者。

int main() {
    using std::map; 
    using std::string; 
    map<string, map<string, string>> test_map {
        {"Hello", {{"A", "B"}, {"C", "D"}}},
        {"World", {{"Blarg", "glug glug glug"}, {"idek what to put here", "felt cute might delete later"}}}
    }; 

    {
        auto output_file = fopen("example.txt", "w"); 
        output::write(output_file, test_map); 
        fclose(output_file); 
    }
    map<string, map<string, string>> map_from_file; 
    {
        auto input_file = fopen("example.txt", "r");
        try {
            input::read(input_file, map_from_file); 
        } catch(std::logic_error& err) {
            std::cerr << "Reading example.txt failed: " << err.what() << '\n'; 
        }
        fclose(input_file);  
    }

    std::cout << std::boolalpha << "Maps equivilant? " << (test_map == map_from_file) << '\n'; 


    for(auto pair : map_from_file) {
        std::cout << '"' << pair.first << "\" -> {\n"; 
        for(auto kv : pair.second) {
            std::cout << "  \"" << kv.first << "\" -> \"" << kv.second << '"' << "\n"; 
        }
        std::cout << "}\n"; 
    }
}

关于python - 如何在 C++ 中高效地创建和编译大 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56875729/

相关文章:

python - 无法使用 Confluent Elasticsearch 接收器连接器将 Kafka 主题数据转换为结构化 JSON

c++ - 编译错误 - 没有匹配的函数可调用 'Exception::Exception(Exception)'

php - 将单列查询值拆分为不同的 php 变量

javascript - 访问 JSON 中的值

python - 使用 python argparse 模块首先报告无效选项(或使用正则表达式)

python - 将多索引 pandas 数据框转换为单索引

python - 从字符串中提取字典

c++ - 链接 : fatal error LNK1104: cannot open file '..\json_spirit\Debug\json_spirit_lib.lib'

c# - C#/Java 中动态对象的限制

javascript - Angular $resource JSON 回调不起作用——这是最佳实践吗?