Si j'ai deux vecteurs STL Vect1, Vect2 et je tiens à produire d'eux une carte, le premier élément de Vect1 correspondra au premier élément de VectT2 et ainsi de suite. Comment puis-je faire ça de la manière la plus simple? P>
5 Réponses :
std::vector<int> a, b; // fill vectors here... std::map<int, int> m; assert(a.size() == b.size()); for (size_t i = 0; i < a.size(); ++i) m[a[i]] = b[i];
Cela fonctionne, mais je remplacerais le affirmer code> avec une exception ou quelque chose. Personne n'aime un appel de bibliothèque qui arrête son programme!
Que se passe-t-il lorsque a code> contient des doublons? Vous voudrez peut-être faire
si (m.find (a [i])! = M.end ()) m.insert (a [i]) d'autre lancer ... code>.
@ALEXANDRE C. Insérer CODE> retournera une paire avec un itérateur dans l'élément et un booléen indiquant s'il a été inséré ou existé auparavant. Il n'est pas nécessaire de faire la recherche précédente.
@David: Je devrais parfois lire les docs! Merci pour cela. Donc, mon commentaire devrait être lu si (! M.insert (std :: make_pair (a [i], b [i])). Deuxièmement) lancer ... code>
@Andre: Assert est généralement ignoré dans les constructions de libération
@ Inverse: c'est une raison supplémentaire de ne pas l'utiliser, en ce qui me concerne. Quelqu'un qui concerne l'utilisation de "portant un gilet de sécurité tout en canoë-kayak à proximité du rivage et le retire avant de sortir au milieu du lac".
S'il y a une clé en double, cette version le remplacera, il aura donc une valeur de la dernière rencontrée.
En supposant, vous allez ignorer l'extra (taille de VecT1! = Taille de VecT2), cela pourrait être une solution:
map<T1, T2> target; //vector<T1> vect1, vector<T2> vect2; vector<T1>::iterator it1 = vect1.begin(); vector<T2>::iterator it2 = vect2.begin(); while(it1 != vect1.end() && it2 != vect2.end()) { target.insert(std::make_pair(*it1, *it2)); it1++;it2++; }
Nous allons utiliser la version de std :: transformer qui prend 2 séquences d'entrée . (Pas aussi bien connu qu'il apparaît comme celui qui prend une séquence unique).
Vous pouvez passer dans J'ai testé le code et il compile bien avec GNU 4.3.2 p> (j'ai également testé maintenant avec c ++ 11. Cela fonctionne quand j'ai changé de make_pair pour prendre INT Const & plutôt que INT). P> Si les deux séquences d'entrée ont une longueur différente, si la première est plus courte et des éléments ultérieurs dans La deuxième séquence sera ignorée. Si le premier est plus long, il produira un comportement indéfini. P> p> std :: make_pair
La bibliothèque standard a déjà un std :: transformez code> algorithme qui prend deux séquences et un objet de fonction binaire.
@BlastFurnace, ERM, pas la dernière fois que j'ai regardé. std :: Transform code> prend une séquence et un itérateur de sortie (où le résultat transformé sera écrit) ...
@Nim: Il est documenté sur le site MSDN et SGI.com/tech/stl/transform. HTML . Il existe deux formes de la std :: transformation code> algorithme.
@BlastFurnace, Shikes j'ai raté ça !! Thx pour pointer cela !!
@Nim: J'ai posté une réponse avec std :: transformer code>. J'ai aussi triché et utilisé une expression de Lambda C ++ 0x car elle rend le tout aussi simple.
hehe, ce ne doit être que moi que cela pense que la version Lambda a l'air horrible ...;)
@Nim: J'aime pouvoir définir le code pour un foncteur unique à l'endroit où il est utilisé. Un lambda peut également être caché dans une variable code> code> si j'ai besoin de le transmettre ou de l'appeler à plusieurs endroits. Ils sont vraiment soignés une fois que vous vous êtes habitué à eux.
@Nim @blastfurnace J'ai regardé la documentation et je vois effectivement STD :: transformer avec 2 entrées qui signifie simplement retirer la mine et la mettre à sa place. Fonctionne-t-il avec make_pair?
OK, testé mon code et ça fonctionne bien. Donc, possible dans une seule déclaration à l'aide de la bibliothèque standard.
Cela ne compilera pas avec l'option -Std = C ++ 11. Je reçois la même erreur avec g ++, clang ++ et iCPC: / usr / include / c ++ / 4.8.1 / bits / stl_algo.h: 4988: 46: Erreur: impossible de lier "int 'lvalue à" int &&' Code> La Lambda fonctionne bien et est probablement la voie à suivre lorsqu'il s'agit de C ++ 11.
Au fait, si vous avez fait cela dans un modèle, vous auriez besoin d'un typename avant V1 :: Value_Type et V2 :: Value_Type.
S'il y a une clé en double ici, le premier compte et la valeur sera arrivée en premier. Pour la transformation C ++ 11 prend une lambda alors utilisez-la. Je suis surpris que cela ne compilait pas. Quel bit est défectueux?
Ce code de travail cassé c ++ 11 est quelque chose que j'ai besoin de demander ici ... Je vais vérifier que cela n'a pas été brisé auparavant.
Incidemment, si les séquences sont différentes longueurs ici, il utilisera la longueur de la première séquence et sera ub si la première est plus longue que la seconde.
Voici une légère variation utilise Boost's Zip_iterator CODE>
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
#include <map>
#include <vector>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>
// this is our map type
typedef std::map<int, std::string> map_t;
map_t::value_type adapt_tuple(const boost::tuple<const map_t::key_type&, const map_t::mapped_type&>& t)
{
return map_t::value_type(t.get<0>(), t.get<1>());
}
int main(void)
{
std::vector<int> keys;
std::vector<std::string> values;
keys.push_back(1);
keys.push_back(2);
keys.push_back(3);
keys.push_back(4);
values.push_back("1");
values.push_back("2");
values.push_back("3");
values.push_back("4");
std::vector<int>::const_iterator beg1 = keys.begin();
std::vector<int>::const_iterator end1 = keys.end();
std::vector<std::string>::const_iterator beg2 = values.begin();
std::vector<std::string>::const_iterator end2 = values.end();
map_t my_map;
// simply iterate over...
std::transform(
boost::make_zip_iterator(
boost::make_tuple(beg1, beg2)
),
boost::make_zip_iterator(
boost::make_tuple(end1, end2)
),
std::inserter(my_map, my_map.end()),
adapt_tuple
);
std::cout << "size of map: " << my_map.size() << std::endl;
return 0;
}
Pouvons-nous remplacer pour la transformation, ce qui vous donnerait une solution similaire à celle de la mienne?
@Cashcow, vous y allez, la version std :: transformez code>, la seule chose que je ne suis pas au courant est quelque chose qui peut déjà adapter un
boost :: tuple code> à un
std :: paire code>, mais où est le plaisir de se conformer ?? ;)
Voici une solution qui utilise des fonctions de bibliothèque standard (et C ++ 0x lambdas). Remarque: Cela suppose que Vec1.Size () n'est pas supérieur à Vec2.Size () . p> p>
Vous n'avez pas besoin de la Lambdas, ce qui suit fonctionne aussi bien en C ++ 03 std :: Transform (Vec1.begin (), Vec1.end (), Vec2.begin (), STD :: Inserteur ( my_map, my_map.end ()), std :: make_pair
@Nim: Peut-être que c'est juste moi mais MSVC ++ n'acceptera pas std :: make_pair code> comme objet de fonction binaire.
Avez-vous essayé std :: make_pair
@CashCow: Oui, mais cela ne compilerait toujours pas. J'ai aussi essayé de l'envelopper avec std :: lid code> avec le même résultat. Lambdas gagne à nouveau.
Que voulez-vous arriver quand ils ont des tailles différentes?