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?

有帮助吗?

解决方案

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.

其他提示

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));
              });
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top