web-dev-qa-db-fra.com

L'égalité std :: unordered_map dépend-elle de l'ordre d'insertion

Si vous créez deux std::unordered_map les conteneurs utilisant le même ensemble de paires clé-valeur (non égales), mais insérés dans un ordre différent (de sorte que les conteneurs contiennent des éléments égaux, mais potentiellement dans des ordres différents), les conteneurs sont garantis égaux, selon l'égalité opérateur ( operator== ). Je suppose que le code de hachage et les opérateurs d'égalité des éléments de conteneur satisfont toutes les contraintes requises sur leur implémentation.

34
Raedwald

Oui, ils sont garantis de retourner égaux dans ce cas. Le libellé spécifique (extrait de N4659, § [unord.req]/12) est le suivant:

Deux conteneurs non ordonnés a et b se comparent égaux si a.size() == b.size() et, pour chaque groupe de clés équivalentes [Ea1, Ea2) Obtenu à partir de a.equal_range(Ea1), il existe un groupe de clés équivalentes [Eb1, Eb2) obtenu à partir de b.equal_range(Ea1), tel que is_permutation(Ea1, Ea2, Eb1, Eb2) renvoie true.

Donc, tant que les clés (et les valeurs associées) dans l'une sont les mêmes que l'autre (mais éventuellement dans un ordre différemment permuté), elle sera comparable.

30
Jerry Coffin

De [unord.red]/12

Deux conteneurs non ordonnés a et b se comparent égaux si a.size() == b.size() et, pour chaque groupe de clés équivalentes [Ea1, Ea2) Obtenu à partir de a.equal_­range(Ea1), il existe un groupe de clés équivalentes [Eb1, Eb2) obtenu à partir de b.equal_­range(Ea1), tel que is_­permutation(Ea1, Ea2, Eb1, Eb2) renvoie true. [...]

Donc, tant que les clés sont les mêmes et que la taille est la même, les conteneurs se comparent égaux, quel que soit l'ordre dans lequel les clés sont.

13
NathanOliver

Ci-dessous sont des citations de cppreference.com sur le std: unordered_map, operator ==,! = (Std :: unordered_map):

Le contenu de deux conteneurs non ordonnés lhs et rhs est égal si les conditions suivantes sont réunies:

  • lhs.size () == rhs.size ()
  • chaque groupe d'éléments équivalents [lhs_eq1, lhs_eq2) obtenu à partir de lhs.equal_range (lhs_eq1) a un groupe correspondant d'éléments équivalents dans l'autre conteneur [rhs_eq1, rhs_eq2) obtenu à partir de rhs.equal_range (rhs_eq1), qui a les propriétés suivantes:
    • std :: distance (lhs_eq1, lhs_eq2) == std :: distance (rhs_eq1, rhs_eq2).
    • std :: is_permutation (lhs_eq1, lhs_eq2, rhs_eq1) == true.

Notez que:

Le comportement n'est pas défini si Key ou T ne sont pas EqualityComparable.

Le comportement est également indéfini si Hash et KeyEqual font (jusqu'à C++ 20) KeyEqual n'a pas (depuis C++ 20) le même comportement sur lhs et rhs ou si l'opérateur == pour Key n'est pas un raffinement de la partition en groupes de clés équivalentes introduits par KeyEqual (c'est-à-dire si deux éléments qui comparent égal à l'aide de l'opérateur == tombent dans des partitions différentes)

Enfin, à considérer est la complexité:

Proportionnel à N appels à l'opérateur == sur value_type, appels au prédicat retourné par key_eq et appels au hasher retournés par hash_function, dans le cas moyen, proportionnels à N2 dans le pire des cas où N est la taille du conteneur.

Par conséquent, si les deux cartes non ordonnées ont la même taille et que chaque clé dans l'un des conteneurs est recherchée dans l'autre plus, s'il se trouve que leurs valeurs sont comparées, elles sont alors considérées comme les mêmes.

3
acarlstein