Domanda

Consider the following:

struct A
{
    int i;
    double d;
    std::string s;
};

std::list<A> list_A; 

I'd like to copy all the elements of list_A to a map such that every pair in the map will consist of an element from list_A as value and its string s as key. Is there a way of doing it that is more elegant than looping through the list and insert each element along with its string as key to the map?

È stato utile?

Soluzione

This should get you the idea of how to use transform:

std::pair<std::string, A> pairify(const A& a) { return std::make_pair(a.s, a); }

std::transform(list.begin(), list.end(), std::inserter(map, map.end()), pairify);

The reason to use the inserter is:

An insert interator is a special type of output iterator designed to allow algorithms that usually overwrite elements (such as copy) to instead insert new elements automatically at a specific position in the container.

Altri suggerimenti

I love standard library algorithms and lambdas but it doesn't get much simpler than:

for (const A& value : list_A) {
    map_A.insert(std::make_pair(value.s, value));
}

The other methods are doing the equivalent of this code and this loop is readable and just as fast.

Sorry answered too quickly last time without details, here is a compilable code.

struct A
{
    int i;
    double d;
    std::string s;
};

std::list<A> list_A;

std::pair<std::string, A> convert(const A &x) {
    return make_pair(x.s,x);
}

int main() {

    std::map<std::string,A> out;

    std::transform(list_A.begin(), list_A.end(), std::inserter(out,out.end()),convert);

}

I may store it in a set: in this way there would not be data duplication in the map (s itself):

struct A
{
    bool operator < (const A& r_) const { return (s < r_.s); }
    int i;
    double d;
    std::string s;
};

std::list<A> list_A;
std::set<A> set_A;

for ( std::list<A>::const_iterator itr = list_A.begin(); itr != list_A.end(); ++itr ) {
    if ( ! set_A.insert(*itr).second ) {
      // Handle duplicated elements
    }
}

I may keep the loop: in this way you could handle duplicated elements correctly.

If you use C++11 you can use lambda function with capture:

std::map<std::string, A> m;
std::list<A> l;
std::for_each(l.begin(), l.end(),
              [&](const A& a) {
                  m.insert(std::make_pair(a.s, a));
              });
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top