2017-10-10 4 views
2

Imaginez que j'ai un tableau d'objets « personne »:Comment obtenir un tableau de membres de données à partir d'un tableau d'objets en C++?

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

Est-il possible d'obtenir un tableau de la même taille avec l'âge (ou le nom) de chaque personne? Je sais comment le faire avec une boucle mais j'espérais qu'il y avait une sorte de "carte" qui pourrait me faire la même chose en une ligne.

+1

['std :: transform'] (http://fr.cppreference.com/w/cpp/algorithm/transform) pourrait être utilisé. Je ne sais pas si ce n'est pas trop accablant cependant. – nwp

+1

Il y aura une boucle si vous êtes celui pour l'écrire ou non. – AndyG

+2

Avec [range-v3] (https://github.com/ericniebler/range-v3): 'persons | ranges :: view :: transform (& Personne :: age) '. – Jarod42

Répondre

1

Voilà comment cela peut se faire avec std::transform, std::back_inserter, et un 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 << " "; 
} 

Sortie:

16 32 

Live demo

MISE À JOUR: pour éviter re inutile -allocations vous pouvez appeler ages.reserve(pp.size()) avant un appel de std::transform

1

Oui, vous pouvez utiliser transform à la fois pour les baies héritées et pour les conteneurs standard tels que std::vector.

Utilisation des tableaux anciens

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; 

En utilisant 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; 

Ceci extrait dynamiquement les âges de toutes les personnes dans le récipient d'origine.

1

Par souci de généralité, je suppose avec tableau que vous voulez dire un tableau dynamique de taille, l'exemple complet serait:

#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; 
} 

ou vous utilisez std::transform qui serait

#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;}); 
} 

En tout Dans le cas contraire, il n'existe aucun moyen magique d'obtenir un tableau de membres à partir d'un tableau d'instances. Il doit y avoir une boucle quelque part (la transformation fait juste un très bon travail pour cacher cette boucle de votre part).

+0

@Ron oui, fixe. Et seulement maintenant j'ai découvert OP demande un one-liner. Cependant, que l'on écrive une fonction ou utilise un algorithme, il peut être fait sur une ligne et directement visible ou non il doit y avoir une boucle – user463035818