简体   繁体   中英

C++ Using std::transform on a vector of structures

I have a C++ application with a struct which looks like:

struct test_struc {
    std::string name;
    int x;
    int y;
    std::vector<int> data;
};

And I would like to transform two std::vector<test_struc> using the lines according to their data element in the structure. So far, I have the code:

std::vector<test_struc> first = <from somewhere else>;
std::vector<test_struc> second = <from somewhere else>;

std::vector<int> result;
std::transform (second.begin(), second.end(), first.begin(), result.begin(), op_xor);

where op_xor is:

int op_xor (int &i,
            int &j) {
    return  i^j;
}

This works well if first and second are vectors of int , but since they are not, I don't know how to tell the code to use the data element of test_struc as arguments to std::transform .

Am I barking up the wrong tree? Or is there a way to do this?

Note that at least with a modern compiler, you probably want to implement the operation as a lambda expression, so it would look something like:

std::transform(second.begin(), second.end(), 
               first.begin(),
               std::back_inserter(result),
               [](test_struct const &a, test_struct const &b) { 
                   return a.y ^ b.y; 
               });

Minor aside: as it was, you had UB, trying to write through result.begin() when the size of result was 0. You could either use back_inserter as above, or you could define result initializing its size to second.size() .

Your binary functor must take two test_struct s:

int op_xor (const test_struct& i,
            const test_struct& j) 
{
    return  42; // replace wit your desired logic.
}

It isn't clear what exactly you want the functor to do, but it should operate on the test_struct s and return an int.

Or use lambdas. And remember size of other vectors must be the same or more than "second"

  result.resize(second.size());
    std::transform(second.begin(), second.end(), first.begin(), result.begin(),
 [](test_struct & one, test_struct & two){ return one.x ^ two.x; });

But Jerry's example with back_inserter is better

Also you can do it using boost::transform and boost phoenix lambdas:

#include <boost/range/algorithm.hpp>
#include <boost/phoenix.hpp>

using boost::phoenix::arg_names::arg1;
using boost::phoenix::arg_names::arg2;

boost::transform(second, first, std::back_inserter(result), (&arg1)->*&test_struc::x ^ (&arg2)->*&test_struc::x);

First and second arguments of boost::transform are ranges, so you do not have to write second.begin(), second.end(), first.begin() here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM