2010-04-26 3 views
0

Dans le code ci-dessous:Comment insérer dans std :: carte

map<string,vector<int>> create(ifstream& in, const vector<string>& vec) 
{ 
    /*holds string and line numbers into which each string appears*/ 
    typedef map<string,vector<int>> myMap; 
    typedef vector<string>::const_iterator const_iter; 

    myMap result; 
    string tmp; 
    unsigned int lineCounter = 0; 

    while(std::getline(in,tmp)) 
    { 
     const_iter beg = vec.begin(); 
     const_iter end = vec.end(); 

     while (beg < end) 
     { 
      if (tmp.find(*beg) != string::npos) 
      { 
       result[*beg].push_back(lineCounter);//THIS IS THE LINE I'M ASKING FOR 
      } 
      ++beg; 
     } 

     ++lineCounter; 
    } 

    return result; 
} 

Comment dois-je faire (chèque en ligne a commenté dans le code) si je veux utiliser la méthode d'insertion de la carte au lieu d'utiliser l'opérateur []?
Merci.

+0

Je parie que Neil Butterworth le sait – Default

+2

Pourquoi voulez-vous remplacer cette ligne? –

+0

La boucle interne sur les éléments de 'vec' est parfaitement normale. Pourquoi n'utilisez-vous pas une boucle 'for' normale? J'ai passé beaucoup de temps à déterminer comment votre boucle différait d'une boucle normale. – MSalters

Répondre

3

Sérieusement, je ne le ferais pas.

Vous ne compliquerez que trop votre code. Vous auriez besoin d'un appel à l'insert pour générer le nouvel élément dans la map, puis le modifier.

Juste pour le plaisir de le faire (en évitant la double recherche, mais la construction d'un vecteur vide inutile):

result.insert(std::make_pair(*beg, std::vector<int>())) 
     .first->second.push_back(lineCounter); 

EDIT: équivalent réel (fonctionnalité et performance):

std::map<std::string,std::vector<int> >::iterator it = result.upper_bound(*beg); 
if (it->first != *beg) { 
    it = result.insert(it, std::make_pair(*beg, std::vector<int>())).first; 
} 
it->second.push_back(lineCounter); 
+0

En fait, vous souhaiterez d'abord rechercher l'élément, afin de déterminer si vous souhaitez effectuer une insertion ou une mise à jour. Cependant, si vous appelez 'insert (paire )', il renverra l'itérateur à l'endroit où il a été inséré. Il n'y a donc aucune recherche nécessaire par la suite. – MSalters

+0

@David Je ne ferais pas cela, je voulais juste savoir comment le faire. –

+0

@MSalters: Je ne sais pas si le commentaire concerne une version précédente de la réponse que j'avais. En tout cas vous devez choisir entre deux mauvaises options: d'une part, vous faites 'find' suivi de' insert' si l'élément n'est pas présent (ce qui nécessite deux recherches pour chaque élément nouvellement inséré), d'autre part vous faites une insertion avec un vecteur vide qui effectuerait une recherche unique mais créerait inutilement un vecteur pour les cas où l'élément existe réellement. –

1

map::insert renvoie un pair contenant un itérateur de l'élément (soit celui qui vient d'être inséré ou celui qui vient d'être inséré avec cette clé) et un booléen indiquant la réussite ou l'échec. Vous pouvez ensuite appeler le iter->push_back(lineCounter) pour ajouter le nouveau numéro de ligne au vecteur.

... et quand vous avez terminé avec tout cela, sachez que c'est exactement ce que operator[] fait pour vous.

1
result.insert(pair<string,vector<int>>(*beg,100), vector<int>()); 
result[*beg].push_back(lineCounter); 

Ceci est plus compliqué (mais plus lent aussi :-) que votre code actuel, puisque ce fait deux choses avec une seule instruction: (implicitement) insère un tableau vide dans la carte, puis ajoute un nouvel élément à le tableau.

Questions connexes