简体   繁体   中英

How to get array of data members from array of objects in c++?

Imagine that I have an array of "person" objects:

#include <iostream>
class person{
public:
   int age;
   std::string name;
};

Is it possible to get an array of the same size with the age (or the name) of each person? I know how to do it with a loop but I hoped there was some kind of "map" that could get me the same in one line.

Yes, you could, using transform both for legacy arrays and for standard containers such as std::vector .

Using legacy arrays

person persons[2] = { { 20, "name1" }, { 21, "name2" } };
for (auto & person : persons)
    cout << person.age << " " << person.name << endl;

decltype(person::age) ages[sizeof(persons)/sizeof(persons[0])];
std::transform(std::begin(persons), std::end(persons), std::begin(ages), [](person & p) -> decltype(person::age) { return p.age; });
for (auto & age : ages)
    cout << age << endl;

Using std::vector

std::vector<person> persons = { { 20, "name1" }, { 21, "name2" } };
for (auto & person : persons)
    cout << person.age << " " << person.name << endl;

std::vector<decltype(person::age)> ages(persons.size());
std::transform(persons.begin(), persons.end(), ages.begin(), [](person & p) -> decltype(person::age) { return p.age; });
for (auto & age : ages)
    cout << age << endl;

This dynamically extracts the ages of all the persons in the original container.

For the sake of generality I assume with array you mean a dynamically sized array, then the full example would be:

#include <string>
struct person {
   int age;
   std::string name;
};

std::vector<int> getAge(std::vector<person> p) { 
   std::vector<int> result;
   result.reserve(p.size());
   for (auto& e : p) result.push_back(e.age);
   return result;
}

or you using std::transform that would be

#include <algorithm>
int  main() {
    std::vector<person> foo(10);
    std::vector<int>    ages(10);
    std::transform(foo.begin(),foo.end(),ages.begin(),[](person& p){return p.age;});
}

In any case, there is no magic way to get an array of members from an array of instances. There must be a loop somewhere (transform just does a very good job at hiding that loop from you).

Here's how it can be done with std::transform , std::back_inserter , and a lambda:

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>

struct person{
   int age;
   std::string name;
};

int main()
{
    std::vector<person> pp = {{16, "Bob"},{32, "Alice"}};
    std::vector<int> ages;
    std::transform(
        pp.begin(), 
        pp.end(), 
        std::back_inserter(ages),
        [](const person& p) -> int { return p.age; });
    for(auto v: ages)
        std::cout << v << " ";
}

Output:

16 32 

Live demo

UPDATE: to avoid unnecessary re-allocations you can call ages.reserve(pp.size()) before a call of std::transform

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