Tri de std :: map en utilisant la valeur

Je dois sortinger une std::map par valeur plutôt que par clé. Y a-t-il un moyen facile de le faire?

J’ai une solution du fil suivant:
std :: map sortinger par données?
Y a-t-il une meilleure solution?

 map testMap; // some code to generate the values in the map. sort(testMap.begin(), testMap.end()); // is there any function like this to sort the map? 

Même si des réponses correctes ont déjà été postées, je pensais append une démonstration de la façon de le faire proprement:

 template std::pair flip_pair(const std::pair &p) { return std::pair(p.second, p.first); } template std::multimap flip_map(const std::map &src) { std::multimap dst; std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), flip_pair); return dst; } int main(void) { std::map src; ... std::multimap dst = flip_map(src); // dst is now sorted by what used to be the value in src! } 

Source associative générique (nécessite C ++ 11)

Si vous utilisez une alternative à std::map pour le conteneur associatif source (tel que std::unordered_map ), vous pouvez coder une surcharge distincte, mais à la fin l’action est toujours la même, un conteneur associatif généralisé utilisant des modèles variadiques peuvent être utilisés pour l’un ou l’autre de ces concepts:

 // flips an associative container of A,B pairs to B,A pairs template class M, class... Args> std::multimap flip_map(const M &src) { std::multimap dst; std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), flip_pair); return dst; } 

Cela fonctionnera pour std::map et std::unordered_map comme source du flip.

J’avais besoin de quelque chose de similaire, mais la carte retournée ne fonctionnerait pas pour moi. J’ai juste copié ma carte (freq ci-dessous) dans un vecteur de paires, puis sortingé les paires comme je le voulais.

 std::vector> pairs; for (auto itr = freq.begin(); itr != freq.end(); ++itr) pairs.push_back(*itr); sort(pairs.begin(), pairs.end(), [=](std::pair& a, std::pair& b) { return a.second < b.second; } ); 

Si vous souhaitez présenter les valeurs d’une carte dans l’ordre sortingé, copiez les valeurs de la carte pour les vectoriser et les sortinger.

J’aime la réponse d’Oli (en retournant une carte), mais elle semble avoir un problème: la carte du conteneur ne permet pas deux éléments avec la même clé.

Une solution consiste à faire dst le type multimap. Un autre consiste à vider src dans un vecteur et à sortinger le vecteur. Le premier nécessite des modifications mineures de la réponse d’Oli, et le second peut être implémenté avec une copie STL concise.

 #include  #include  #include  #include  #include  using namespace std; int main() { map m; m[11] = 1; m[22] = 2; m[33] = 3; vector > v; copy(m.begin(), m.end(), back_inserter > >(v)); for (size_t i = 0; i < v.size(); ++i) { cout << v[i].first << " , " << v[i].second << "\n"; } return 0; }; 

Vous ne pouvez pas sortinger un std::map cette façon, car les entrées de la carte sont sortingées par la clé. Si vous souhaitez sortinger par valeur, vous devez créer une nouvelle std::map avec une clé et une valeur échangées.

 map testMap; map testMap2; // Insert values from testMap to testMap2 // The values in testMap2 are sorted by the double value 

Rappelez-vous que les doubles clés doivent être uniques dans testMap2 ou utiliser std::multimap .

Pour utiliser la solution d’Oli ( https://stackoverflow.com/a/5056797/2472351 ) à l’aide de multimaps, vous pouvez remplacer les deux fonctions de modèle utilisées par les suivantes:

 template  multimap flip_map(map & src) { multimap dst; for(map::const_iterator it = src.begin(); it != src.end(); ++it) dst.insert(pair(it -> second, it -> first)); return dst; } 

Voici un exemple de programme qui montre toutes les paires clé-valeur conservées après avoir effectué le flip.

 #include  #include  #include  #include  using namespace std; template  multimap flip_map(map & src) { multimap dst; for(typename map::const_iterator it = src.begin(); it != src.end(); ++it) dst.insert(pair(it -> second, it -> first)); return dst; } int main() { map test; test["word"] = 1; test["spark"] = 15; test["the"] = 2; test["mail"] = 3; test["info"] = 3; test["sandwich"] = 15; cout << "Contents of original map:\n" << endl; for(map::const_iterator it = test.begin(); it != test.end(); ++it) cout << it -> first << " " << it -> second << endl; multimap reverseTest = flip_map(test); cout << "\nContents of flipped map in descending order:\n" << endl; for(multimap::const_reverse_iterator it = reverseTest.rbegin(); it != reverseTest.rend(); ++it) cout << it -> first << " " << it -> second << endl; cout << endl; } 

Résultat:

entrer la description de l'image ici

Un std::map sortingé par sa valeur est essentiellement un std::set . Le moyen le plus simple est de copier toutes les entrées de la carte dans un ensemble (sockets et adaptées à partir d’ ici ).

 template  void MapToSet( const M & m, S & s ) { typename M::const_iterator end = m.end(); for( typename M::const_iterator it = m.begin(); it != end ; ++it ) { s.insert( it->second ); } } 

Une mise en garde: si la carte contient des clés différentes ayant la même valeur, elles ne seront pas insérées dans l’ensemble et seront perdues.

Dans l’exemple de code suivant, j’ai écrit un moyen simple de générer des mots clés dans une carte word_map où key est ssortingng (word) et value est unsigned int (occurrence de mot).

L’idée est simple, trouvez le mot haut actuel et supprimez-le de la carte. Ce n’est pas optimisé, mais cela fonctionne bien lorsque la carte n’est pas grande et il suffit de sortir les N premiers mots au lieu de sortinger la carte entière.

 const int NUMBER_OF_TOP_WORDS = 300; for (int i = 1; i <= NUMBER_OF_TOP_WORDS; i++) { if (word_map.empty()) break; // Go through the map and find the max item. int max_value = 0; string max_word = ""; for (const auto& kv : word_map) { if (kv.second > max_value) { max_value = kv.second; max_word = kv.first; } } // Erase this entry and print. word_map.erase(max_word); cout << "Top:" << i << " Count:" << max_value << " Word:<" << max_word << ">" << endl; } 

La structure retournée peut ne plus être une carte mais plutôt un multimap, ainsi dans l’exemple flip_map, tous les éléments de B n’apparaîtront pas nécessairement dans la structure de données résultante.

U peut envisager d’utiliser boost :: bimap qui pourrait vous donner l’impression que la carte est sortingée par clé et par valeurs simultanément (ce n’est pas ce qui se passe réellement)