Comment puis-je trier une std::map d'abord par la valeur, puis par la clé?
J'ai besoin de trier un std::map
par valeur, par clé. La carte contient des données comme suit:
1 realistically
8 really
4 reason
3 reasonable
1 reasonably
1 reassemble
1 reassembled
2 recognize
92 record
48 records
7 recs
J'ai besoin d'obtenir les valeurs dans l'ordre, mais le comble, c'est que les clés doivent être dans l'ordre alphabétique d'après les valeurs sont dans l'ordre. Comment puis-je faire cela?
- utilisez-vous un std::map pour stocker les données ?
- Mettre le std::pair<int, std::string>s dans une liste et de les trier.
- oui, il est stocké dans une carte.
- Je sais qui permettrait de mettre les valeurs dans l'ordre, mais alors ne serait-il garder les clés dans l'ordre alphabétique, après tri des valeurs?
- tri sur les paires sortes sur en premier, puis le deuxième élément. Voir here
- uniquement la valeur de stackoverflow.com/questions/2699060/stl-map-sort-by-value
- Vous pouvez utiliser
std::multimap
avec votrevalues
commekeys
car il permet de dupliquer des clés et de travailler avec desstd::sort
Vous devez vous connecter pour publier un commentaire.
std::map
permettra de trier les éléments parkeys
. Il ne se soucie pas de lavalues
lors du tri.Vous pouvez utiliser
std::vector<std::pair<K,V>>
puis de les trier à l'aide destd::sort
suivie parstd::stable_sort
:Le premier type doit utiliser
std::sort
car il estnlog(n)
, et ensuite utiliserstd::stable_sort
qui estn(log(n))^2
dans le pire des cas.Note que bien que
std::sort
est choisi pour des raisons de performances,std::stable_sort
est nécessaire pour le bon de commande, vous souhaitez que la commande soit par valeur, d'être conservé.@gsf a noté dans le commentaire, vous pouvez utiliser seulement
std::sort
si vous choisissez un comparateur qui comparevalues
d'abord, et S'ils sont égaux, trier leskeys
.Qui doit être efficace.
Mais attendez, il ya une meilleure approche: magasin
std::pair<V,K>
au lieu destd::pair<K,V>
et puis vous n'avez pas besoin de tout comparer à tous — le standard de comparaison pourstd::pair
serait suffisant, qu'il comparefirst
(qui estV
) d'abord, puissecond
qui estK
:Qui devrait fonctionner à merveille.
key
ouvalue
) est triée, vous n'avez qu'àstable_sort
pour trier les autres qui ne sont pas triées.there is a better approach: store std::pair<V,K> instead of std::pair<K,V> and then you don't need any comparer at all
travaillerait même si vous voulez extraire une valeur basée sur la clé?std::multimap
Vous pouvez utiliser
std::set
au lieu destd::map
.Vous pouvez stocker à la fois la clé et la valeur dans
std::pair
et le type de conteneur ressemblera à ceci:std::set
seront le tri des valeurs à la fois par l'origine des clés et des valeurs qui ont été stockés dansstd::map
.Comme expliqué dans Nawaz du réponse, vous ne pouvez pas trier votre carte en elle-même que vous en avez besoin, parce que
std::map
trie les éléments de base sur les touches seulement. Donc, vous avez besoin d'un autre conteneur, mais si vous devez vous en tenir à votre carte, alors vous pouvez toujours copier son contenu (temporairement) dans une autre structure de données.Je pense, la meilleure solution est d'utiliser un
std::set
stockage retourné paires clé-valeur, comme présenté dans la ks1322 de réponse.Le
std::set
est triée par défaut et la ordre des paires est exactement comme vous le souhaitez:De cette façon, vous n'avez pas besoin d'un supplément de tri étape et le code résultant est très courte:
De sortie:
Code sur Ideone
Remarque: Depuis C++17 vous pouvez utiliser gamme pour les boucles avec structuré liaisons pour itérer sur une carte.
En conséquence, le code de la copie de votre carte devient encore plus court et plus lisible:
std::map
déjà trie les valeurs à l'aide d'un prédicat vous définir oustd::less
si vous ne fournissez pas un.std::set
permettra également de stocker les éléments dans l'ordre de les de définir un élément de comparaison. Toutefois, ni ensemble, ni carte vous permettant d'avoir plusieurs clés. Je suggère la définition d'unstd::map<int,std::set<string>
si vous voulez le faire à l'aide de votre structure de données seul. Vous devez aussi réaliser questd::less
pour la chaîne de tri lexicographiquement non par ordre alphabétique.EDIT: Les deux autres réponses faire un bon point. Je suis en supposant que vous souhaitez commander dans une autre structure, ou dans le but de les imprimer.
"Meilleur" peut signifier un certain nombre de choses différentes. Voulez-vous dire par "plus facile," "le plus rapide", "la plupart efficace", "moins de code" "plus lisible?"
Le plus évident de l'approche est de faire une boucle par deux fois. Sur la première passe, l'ordre des valeurs:
Puis sur la deuxième passe, classer par ordre alphabétique les mots, mais seulement si leurs valeurs correspondent.
À proprement parler, c'est un "tri à bulles" qui est lent, car à chaque fois que vous faire un échange, vous devrez recommencer. Un "pass" est terminé une fois que vous obtenez par le biais de l'ensemble de la liste sans faire de swaps.
Il existe d'autres algorithmes de tri, mais le principe est le même: à l'ordre par la valeur, puis les classer par ordre alphabétique.