2017-10-19 5 views
0

J'ai créé deux cartes de la forme:Fusion de deux cartes C++

[numéro d'événement] [masse] appelée carte results_JMass

et

[numéro d'événement] [momentum] appelé carte results_PhotonPt

Les deux cartes ont la même clé (numéro d'événement) qui est un nombre entier et contient des doubles comme valeurs. Je voudrais créer une troisième carte de la forme:

[numéro d'événement] [masse] [mouvement]

Je sais que je dois utiliser

std::map <Int_t, std::vector< pair <Double_t,Double_t> > > new_map; 

Mais je ne suis pas sûr comment combiner les deux cartes pour créer la troisième.

C'est ce que je suis venu avec:

for (auto& kv3 : results_JMass) { //Iterates the data with kv3 as the iterator and the results_jMass what kv3 is iterating through 
    event_number = kv3.first; //Iterator for the first index, i.e the events 
    m = kv3.second; //iterator for the second index i.e the masses 

    new_map [event_number].first = m; 

    for (auto&kv4: results_PhotonPt) { 
event_number = kv4.first; 
p = kv4.second; 

new_map [event_number].second = p; 
    } 
} 
+1

sont les deux cartes garanties pour contenir le même ensemble de numéros d'événement? – Steve

+0

Sans rapport avec votre question, mais qu'est ce que Int_t et Double_t? Sont-ils normaux 'int' et' double'? Pourquoi les noms de types personnalisés? –

+4

Il me semble que la façon correcte d'exprimer la carte devrait être: 'std :: map > new_map;' – Amadeus

Répondre

1

Si vous êtes sûr à 100%, que les deux cartes ont exactement les mêmes touches, puis une boucle suffit:

std::map < Int_t, pair <Double_t,Double_t> > new_map; 
auto it = second_map.begin(); 
for(const auto &p : first_map) 
    new_map.emplace(p.first, std::make_pair(p.second, (it++)->second)); 

ou pour 98 C++

std::map < Int_t, pair <Double_t,Double_t> > new_map; 
second_map_type::const_iterator it2 = second_map.begin(); 
for(first_map_type::const_iterator it1 = first_map.begin(); it1 != first_map.end(); ++it1) 
    new_map.insert(std::make_pair(it1->first, std::make_pair(it1->second, (it2++)->second))); 
+0

Suppose l'utilisation de C++ 11, qui n'était pas mentionnée en question. – Steve

+1

@Steve qui est standard pendant 6 ans, je pense que nous pouvons le supposer sauf indication contraire. Quoi qu'il en soit, il est assez simple de le réécrire en utilisant C++ 98 – Slava

+0

alors pourquoi y a-t-il une balise séparée sur SO, si C++ est censé impliquer C++ 11? – Steve

2

En supposant que vous vouliez dire:

std::map < Int_t, pair <Double_t,Double_t> > new_map; 

itérer sur la première carte, et ajoutez la clé et la valeur à votre nouvelle carte en utilisant:

Ensuite, passez en revue la deuxième carte, puis ajoutez la clé et la valeur à la nouvelle carte:
new_map [event_number].second = momentum; 

J'ai supposais les 2 cartes sources contiennent la même liste exacte des numéros d'événement, juste avec des données différentes - sinon, vous aurez des entrées new_map qui contiennent seulement un ou l'autre des données

+0

Merci, oui les 2 cartes sources contiennent exactement la même liste de numéros d'événements mais avec des données différentes. Donc, je parcourir sur la première carte dans une boucle for, puis-je itérer sur la deuxième carte dans une seconde boucle dans la première boucle for ou entièrement séparément? –

+0

@AmyTee 'new_map [numéro_événement] = {mass_map [event_num], momentum_map [event_num]}' devrait suffire. Pas besoin de plusieurs instructions ou de variables temporaires. En utilisant ['std :: transform'] (http://en.cppreference.com/w/cpp/algorithm/transform) et [lambdas] (http: //en.cppreference.com/w/cpp/language/lambda) pourrait le raccourcir encore plus. –

+1

Si vous parcourez déjà l'une des cartes pour obtenir l'event_number, vous pouvez également faire new_map [numéro_événement] = {masse, momentum_map [numéro_événement]} 'et enregistrer une recherche supplémentaire. Lambdas nécessiterait C++ 11, ce qui n'était pas mentionné dans la question initiale. – Steve

0

On peut utiliser un algorithme similaire à set_intersect tout en même temps prouver que les données d'entrée est correct pour (presque) zéro coût:

#include <map> 
#include <utility> 
#include <limits> 

using mass_map = std::map<int, double>; 
using moment_map = std::map<int, double>; 

using mass_moment_map = std::map < int, std::pair <double,double> >; 

bool merge_mass_and_moment(mass_map const& mass, 
          moment_map const& moment, 
          mass_moment_map& target, 
          mass_moment_map& exceptions) 
{ 
    target.clear(); 
    exceptions.clear(); 

    auto current_mass = mass.begin(); 
    auto current_moment = moment.begin(); 

    while (current_mass != mass.end() && current_moment != moment.end()) 
    { 
     if (current_mass->first < current_moment->first) 
     { 
      exceptions.emplace(current_mass->first, 
           std::make_pair(current_mass->second, std::numeric_limits<double>::infinity())); 
      ++ current_mass; 
     } 
     else if (current_moment->first < current_mass->first) 
     { 
      exceptions.emplace(current_moment->first, 
           std::make_pair(std::numeric_limits<double>::infinity(), current_moment->second)); 
      ++ current_moment; 
     } 
     else 
     { 
      target.emplace(current_moment->first, 
          std::make_pair(current_mass->second, current_moment->second)); 
      ++current_mass; 
      ++current_moment; 
     } 
    } 

    while (current_mass != mass.end()) 
    { 
     exceptions.emplace(current_mass->first, 
          std::make_pair(current_mass->second, std::numeric_limits<double>::infinity())); 
     ++ current_mass; 
    } 

    while(current_moment != moment.end()) 
    { 
     exceptions.emplace(current_moment->first, 
          std::make_pair(std::numeric_limits<double>::infinity(), current_moment->second)); 
     ++ current_moment; 
    } 

    return exceptions.empty(); 
}