How to slice map of structs into a sub-set with the same keys?

Viewed 49

I have a map of structs that holds several named values like this:


struct MyData {
    MyType dataA;
    std::string dataB;
    int dataC;
  };

typedef std::pair<std::string, MyData> PairType;

std::map<PairType::first_type, PairType::second_type> dataMap;

This is defined in a header file of a compilation unit that calls a function from a library. Because the library function does not know about my type definitions, I can't pass dataMap directly. The function only actually needs the dataA struct member and already knows about MyType, so I could pass a std::map<std::string, MyType> instead.

Whats the most elegant way of cutting just the data I need from the map of structs and save it into a new map with the same keys but only the type and values from dataA?

Preferably for C++0x without usage of boost or other external libraries, but solutions for newer standards are also welcome for educational purposes.

I'm basically looking for an equivalent of Python's

newDict = {key:value.dataA for (key,value) in oldDict.items()}
2 Answers

You can use a ranged based for loop to really easily make a copy. That would look like

std::map<std::string, MyType> my_type_map;
for (const auto& pair : dataMap)
{
    my_type_map.emplace(pair.first, pair.second.dataA);
} 

If you want this as a single expression, you are going to need something like boost::transform_iterator, either by including that, or writing an iterator yourself.

Given a conversion function (or equivalent lambda)

std::pair<std::string, MyType> convert(PairType& pair){ 
    return { pair.first, pair.second.dataA }; 
};

You can declare newDict and populate it

/* can be const */ std::map<std::string, MyType> newDict { 
    boost::make_transform_iterator(oldDict.begin(), convert), 
    boost::make_transform_iterator(oldDict.end(), convert) 
};

Or you can use a view type

auto newDict = boost::copy_range<std::map<std::string, MyType>>(oldDict | std::ranges::views::transform(convert));
Related