【问题标题】:Initialize a map with regex使用正则表达式初始化地图
【发布时间】:2021-07-14 08:34:51
【问题描述】:

我正在使用一个非常漂亮且简单的std::vector<std::string> 初始化程序,它接受输入字符串和正则表达式。它类似于基本拆分,只是它适用于正则表达式 Group1 匹配:

static std::vector<std::string> match(const std::string& str, const std::regex& re) {
    return { std::sregex_token_iterator(str.begin(), str.end(), re, 1), std::sregex_token_iterator() };
}

向量的构造如下:

std::string input = "aaa(item0,param0);bbb(item1,param1);cc(item2,param2);";
std::vector<std::string> myVector = match(input, std::regex(R"(\(([^,]*),)"));

这会产生一个包含item0,item1,item2 的向量,该向量是从使用正则表达式的输入字符串中提取的:

现在我的match 函数使用正则表达式的第一组结果并且(我相信)使用vector 的初始化形式:

std::vector<std::string> myVector = { ... };

我想创建一个类似的match 函数来构造std::map&lt;std::string,std::string&gt;。 Map 也有上面的初始化器:

std::map<std::string,std::string> myMap = { {...}, {...} };

我的想法是修改正则表达式以创建更多组结果:

我想修改上面的 match 函数,用修改后的正则表达式 (\(([^,]*),([^)]*)) 为我创建一个漂亮的地图,结果与此相同:

std::map<std::string,std::string> myMap = { {"item0", "param0"}, {"item1", "param "}, {"item2", "param2"}, };

我尝试了什么?

static std::map<std::string, std::string> match(const std::string& str, const std::regex& re) {
    return { std::sregex_token_iterator(str.begin(), str.end(), re, {1,2}), std::sregex_token_iterator() };
}

这个(如果是向量)会将 Group1Group2 结果放入向量中。但它无法初始化地图。

我怎样才能做到这一点轻松sregex_token_iterator 不可能)?

【问题讨论】:

    标签: c++ regex dictionary iteration regex-group


    【解决方案1】:

    我不知道“容易”到底是什么意思,所以简单解决方案来了:

    #include <iostream>
    #include <regex>
    #include <vector>
    
    static std::map<std::string, std::string> match(const std::string& str, const std::regex& re) {
        std::map<std::string, std::string> retVal;
        auto token = std::sregex_token_iterator(str.begin(), str.end(), re, {1,2});
        for (auto it=token++, jt=token; it != std::sregex_token_iterator(); ++it, jt = it++)
            retVal.emplace(*it,*jt);
        return retVal;
    }
    
    int main() {
        std::string input = "aaa(item0,param0);bbb(item1,param1);cc(item2,param2);";
        auto myVector = match(input, std::regex(R"(\(([^,]*),([^)]*))"));
        for (const auto& item : myVector)
            std::cout<<item.first<<'\t'<<item.second<<std::endl;
    }
    

    您也可以尝试使用boost和自制的generic algorithm

    【讨论】:

    • 看起来很有希望,是否有可能以某种方式跳过循环?
    • 我相信循环不能被跳过,只能隐藏在引擎盖下。为什么要隐藏循环?
    • 不客气!我只是不知道如何处理每次使用std::transform 之类的东西将迭代器推进两步。我认为这是可能的,但我几乎可以肯定该解决方案在质量上不会与上面链接中提供的不同。
    猜你喜欢
    • 2011-07-10
    • 2013-05-28
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多