Ken Y-N
Ken Y-N

Reputation: 15009

Using std::transform to convert a std::vector<struct{key; val;}> into a std::map<key, val>

Given these types:

struct ComplexLibraryThing { /*lots of fields*/};
typedef std::map<int, ComplexLibraryThing> MyMap;
struct ShadowComplexLibraryThing { /*Shadow of ComplexLibraryThing*/};
struct MyVecType { int a; ShadowComplexLibraryThing b; };
typedef std::vector<MyVecType> MyVector;

I can do this for serialisation (my serialisation library doesn't support map-like types):

MyVecType map2pair(std::pair<int, ComplexLibraryThing> const &myPair)
{
    MyVecType retVal;
    retVal.a = myPair.first;
    retVal.b = convertForSerialisation(myPair.second);
    return retVal;
}

MyMap myMap = {...};
MyVector myVector;
std::transform(myMap.begin(),
               myMap.end(),
               std::back_inserter(myVector),
               map2pair);

I then send the vector over to the receiver which wants to reconstruct the MyMap. However, I cannot find a suitable <algorithm> template that does de-serialisation like this:

MyMap myNewMap;
for (auto const &entry: myVector)
    myNewMap[entry.a] = convertForDeserialisation(entry.b);

How would I write this using an <algorithm>?

(Note that the ComplexLibraryThing type within the map cannot be easily altered, but I also have a ShadowComplexLibraryThing which can be)

Upvotes: 3

Views: 5675

Answers (2)

druckermanly
druckermanly

Reputation: 2741

I think the key "trick" missing is std::inserter. Here's a little demo.

#include <algorithm>
#include <iterator>
#include <map>
#include <vector>

struct foo {int a; int b;};

std::vector<foo> GenerateSource() {
  return {};
} 

std::pair<int, int> ConvertFooToMapPair(const foo& f) {
    return {f.a, f.b};
}

int main(int argc, char* argv[]) {
  std::map<int, int> destination;
  std::vector<foo> source = GenerateSource();
  std::transform(
    source.begin(), source.end(),
    std::inserter(destination, destination.end()),
    ConvertFooToMapPair);
}

Upvotes: 6

Zalman Stern
Zalman Stern

Reputation: 3191

This post shows how to create an inserter for std::map:

How to insert into std::map?‌​p

The type of the thing iterated over needs to be a std::pair<KeyType, EntryType> (the so called value_type of std::map).

I think this looks like so:

std::pair<int, ComplexLibraryThing> vec2pair(const MyVecType &myVec)
{
    return std::make_pair(myVec.a,
                          transformForDeserialization(myVec.b));
}

MyVector myVector = {...};
MyMap myMap;
std::transform(myVector.begin(),
               myVector.end(),
               std::inserter(myMap, myMap.end()),
               vec2pair);

Upvotes: 4

Related Questions