Search code examples
c++regexdictionaryiterationregex-group

Initialize a map with regex


I'm using a very nice and simple std::vector<std::string> initializer which takes an input string and regex. It's similar to a basic split, just it works with regex Group1 matches:

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() };
}

Construction of a vector is done like below:

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

This results a vector containing item0,item1,item2 extracted from an input string with regex:

enter image description here

Now my match function uses the first group results of the regex and (I believe) utilizes the vector's intialization form of:

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

I'd like to create a similar match function to construct a std::map<std::string,std::string>. Map also has the above initializator:

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

My idea is to modify the regex to create more group results:

enter image description here

And I would like to modify the above match function to create a nice map for me with the modified regex (\(([^,]*),([^)]*)), resulting the same as this:

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

What I've tried?

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() };
}

This one (in case of a vector) would put both Group1 and Group2 results into the vector. But it can not initialize a map.

How can I still do that easily (Is it not possible with sregex_token_iterator)?


Solution

  • I don't know what 'easily' does mean exactly, so here comes simple solution:

    #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;
    }
    

    You can also could try to use boost and homemade generic algorithm.