La description de ton problème me fait typiquement penser à une structure Union-find, couplée par exemple à un dictionnaire : tu peux regrouper des clefs ensemble dans ton union-find (par exemple, 'a'
, 'b'
et 'c'
), et étant donnée une clef, trouver à quelle classe elle appartient et utiliser cette classe comme clef de ton dictionnaire pour connaître la valeur associée.
La solution proposée par victor et entwanne (deux dictionnaires, dans les deux sens) est un peu différente, et j’ai l’impression qu’elle répond assez bien au problème « je veux pouvoir grouper une clef avec une autre » : on récupère la valeur X associée au groupe et on l’affecte à la nouvelle clef à grouper dans le dictionnaire direct, et on ajoute cette clef à grouper dans la valeur associée à X dans le dictionnaire indirect tout en l’enlevant de son ancienne valeur. Tout est en temps constant.
Ça permet aussi de résoudre efficacement le problème de « je veux pouvoir connaître toutes les clefs auxquelles est associée une certaine valeur » (sans reparcourir tout le dictionnaire, ce qui serait particulièrement inefficace), mais j’ai l’impression qu’il ne fait pas partie de ce que tu demandes (après le problème XY, la solution YZ ? :-D) Si on met de côté les groupes de clefs, c’est même la solution évidente pour résoudre ce problème, qui peut en effet aussi s’écrire comme « je veux une association clef/valeur mais aussi une association valeur/clef ».
Par contre, pour changer une valeur associée à un groupe, c’est plus compliqué. Le dictionnaire indirect te permet d’éviter de parcourir tout ton dictionnaire direct, mais il faut quand même, dans le dictionnaire direct, changer la valeur associée à chaque élément de ton groupe. Pan, $O(n)$ : la même complexité que si tu utilisais des bêtes listes d’association.
La solution avec l’union-find te permet d’éviter ça et d’avoir du $O(\log n)$ un peu partout, pour un coût en mémoire qui a l’air à peu près similaire. C’est vraiment un cas d’école d’utilisation de cette structure.
Note qu’il reste à mon avis quelque chose de pas clair dans la définition de ton problème : qu’est-ce qui se passe si par hasard deux clefs ont la même valeur associée alors que tu ne voulais pas les grouper, et que tu veux changer la valeur d’une des deux ? Est-ce que la deuxième veut changer aussi ? C’est difficile de répondre à ta place, et tu n’as pas donné suffisamment d’informations sur ton problème de départ pour savoir, mais mon intuition est que le comportement où on groupe les clefs explicitement ou pas du tout est plus logique. Si tu veux retrouver l’autre comportement, ajouter un union-find aux doubles dictionnaires de victor m’a l’air d’être la bonne solution (quand je change une valeur, je vérifie si elle n’est pas déjà présente ailleurs, et le cas échéant je fusionne les deux classes. La complexité globale de la mise à jour reste la même, c’est informagique.)
PS : une recherche très rapide « union find python » me donne pas mal de résultats, dont aucun ne me semble être universellement validé par la communauté. Ça fait trop longtemps que je n’ai pas utilisé sérieusement ce langage pour t’en proposer une, mais je suis à peu près certain qu’il y en a au moins une de qualité dans le lot.