Gestion du contenu d'un dictionnaire comme une fonction

Hello Forum,

J'ai une question sur la gestion d'un dictionnaire. Peut on trouver une clé à partir de la valeur qui lui est associée?

Prenons un exemple, pour des clé en lettres et des valeurs associées en chiffres dans le dictionnaire nommé DICO:

a-->1

b-->2

c-->3

d-->8

e-->1

f-->8

Ainsi,

Quelle(s) clé(s) correspond(ent) à la valeur 1 : réponse(s): a, e

Quelle(s) clé(s) correspond(ent) à la valeur 2 : réponse(s): b

Quelle(s) clé(s) correspond(ent) à la valeur 3 : réponse(s): c

Quelle(s) clé(s) correspond(ent) à la valeur 8 : réponse(s): d, f

De plus, est-il possible sans avoir à parcourir DICO, d'accéder directement à une des valeurs comme on fait dans le cas des tableaux et fonctions?

Par exemple:

Dico(a)=1 et / ou Dico(1)=a, e

Dico(b)=2 et / ou Dico(2)=b

Dico(c)=3 et / ou Dico(3)=c

Merci d'avance pour vos excellentes contributions.

Bien à vous,

Yeshua.

Bonjour,

un dictionary ne fonctionne que dans le sens une clé donne sa valeur.

Sinon il faut boucler sur toutes les clés ou te créer 2 dictionaries.

eric

Bonjour,

c'est tout l'intérêt des dictionnaires d'accéder aux valeurs avec une clé.

il suffit d'écrire :

MonDico("clé")

Par contre récupérer une clé en ayant un indice n'est pas possible, il faut boucler. Tu peux te créer une fonction personnalisée qui te fais ça par contre.

Voici un exemple :

Sub test()

Set dico = New Dictionary

dico.Item("a") = 1
dico.Item("b") = 2
dico.Item("c") = 3
dico.Item("d") = 8
dico.Item("e") = 1
dico.Item("f") = 8

MsgBox getKey(dico, 8) 'J'ai mis 8 de manière arbitraire mais c'est ici qu'on met ce qu'on doit chercher

End Sub
Function getKey(dictionnary, value)

getKey = "La valeur " & value & " a été trouvé aux indices suivants : " & vbCr

For Each v In dictionnary.Keys
    If dictionnary(v) = value Then getKey = getKey & v & vbCr
Next

End Function

Bonjour Eriiic

Merci beaucoup. Je pensais que ce serait possible, comme dans d'autres langages.

Bon je vais tenter l'option, boucles dans une fonction alors dans ce cas. Merci encore.

Bonjour Melch,

Merci beaucoup pour votre contribution. Je vais l'adapter.

Quelle version de VBA avez vous sinon? J'aime bien celle là qui définit un dictionnaire directement en utilisant

dim Dico as dictionary
set Dico= new dictionary.

Elle est plus rapide que la mienne où je suis obligé de passer par

Dim Dico as object
set Dico=createobject("Scripting.dictionary")

Je la trouve plus longue… Est-ce une question de version d'excel?

Pour passer directement par :

Set dico = new Dictionnary

Il suffit d'activer la référence "Microsoft Scripting Runtime:

Dans l'éditeur VBA > Outils > Références et cocher la case devant Microsoft Scripting Runtime

Re,

Melch,

La fonction Getkey utilise "dictionary" en variable. C'est ici un nom de variable ou un type de variable ?

Car si j'ai bien compris, dans ma version d'excel, le type de variable "dictionary" n'existe pas. (D'où la question que je posais précédemment).

Yeshua.

re ,

Melch,

Oui, c'est la référence de base qui fait fonctionner aussi " Createobject("Scripting.dictionary") ". Elle est donc activée d'office.

Yeshua.

C'est une fonction que j'ai créée.

Elle prend 2 arguments : le dictionnaire dans laquelle effectuer la recherche, et la valeur à chercher. Elle renvoie une chaine de caractère avec les indices trouvés.

Bon je vais tenter l'option, boucles dans une fonction alors dans ce cas.

pourquoi ne pas te créer un 2nd dictionary en même temps que tu crées le premier ?

eric

Re,

J'ai adapté votre code qui fonctionne à merveille !!!

Je m'attendais à avoir un MsgBox à chaque parcours de boucle. J'ai acquis un plus aujourd'hui. L'affichage du MsgBox se fait en une seule fois et liste les élément au lieu de plusieurs MsgBox pour chaque éléments à afficher.

Il ne me restera plus qu'à chercher comment récupérer les sorties de la fonction.

Pouvez-vous m'expliquer qu'est ce qui fait que l'instruction

getKey = getKey & key & vbCr
 

ne répète pas à l'affichage, la ligne:

 "La valeur " & value & " a été trouvé aux indices suivants : " & vbCr
  

deux fois ?

Hello Eric,

Je ne vois pas comment procéder en vérité. Je ne sais utiliser les dictionnaires que pour un affichage de listes sans doublons.

Je sais parcourir les clés, les items, faire un affichage en ligne ou colonne des valeurs (clés, items, couple(clé, items). Je maîtrise moins l'accès à un élément en particulier, ou une valeur en particulier (en dehors du Dico(clé)=item que je connais).

Yeshua.

Le retour de la fonction est initialisé avec le texte suivant :

"La valeur " & value & " a été trouvé aux indices suivants : " & vbCr

(vbcr signifie retour à la ligne)

ensuite l'instruction :

getKey = getKey & key & vbCr

Prends la chaine de caractère, y ajoute la clé et y ajoute un nouveau saut de ligne.

Comme ça à chaque boucle, si une clé est trouvée, elle est placée une ligne en dessous.

A chaque fois on part de la chaine, a laquelle on rajoute des éléments à la suite.

Je ne vois pas comment procéder en vérité

Je ne comprend pas.

Ton dictionnaire n'est pas apparu ex-nihilo ?

Tu l'as créé donc tu sais faire

Re,

Melch,

Merci beaucoup pour ces détails. Je comprends mieux la méthode d'initialisation du retour de la fonction. C'est très bien, c'est la partie qui me manquait à tout comprendre.

Merci.

Yeshua.

Re,

Eric,

Oui, je dois probablement savoir le faire, créer deux dictionnaires. Je me demandais juste l'astuce pour obtenir des deux dictionnaires, la sortie attendue.

Ma première intension par cette méthode:

Créer le premier dictionnaire avec le couple (clé= clé, valeur= valeur) et le deuxième dictionnaire avec le couple (clé= valeur, valeur= clé). Boucler en imbriqué sur les deux.

dim a as range
set a=wb.ws.range("A1")

for each key1 in dico1.keys
    for each key2 in dico2.keys
        if dico1(key1)=key2 then 
            a.value=dico2(key2)
            set a=a.offset(1)
        endif
    next key2
next key1

Il faut faire les 2 en même temps, inutile de reboucler sur le 1er :

    Dim dict1, dict2, lig As Long, pl() As Variant
    Set dict1 = CreateObject("Scripting.Dictionary")
    Set dict2 = CreateObject("Scripting.Dictionary")
    pl = [A2:B2].Resize(Cells(Rows.Count, 1).End(xlUp).Row - 1).Value
    For lig = 1 To UBound(pl)
            dict1(pl(lig, 1)) = pl(lig, 2)
            If dict2.exists(pl(lig, 2)) Then dict2(pl(lig, 2)) = dict2(pl(lig, 2)) & "," & pl(lig, 1) Else dict2(pl(lig, 2)) = pl(lig, 1)
    Next lig

Un dictionnaire ne contenant qu'une valeur tu es obligé de les concaténer dans le 2nd dictionary.

A l'utilisation, si tu ne trouves pas dans le 1er dict, c'est que c'est dans le 2nd :

    ' recherche
    clé = 8
    If dict1.exists(clé) Then item = dict1(clé) Else item = dict2(clé)

valeur multiple que tu peux ensuite éclater en tableau si besoin :

If InStr(item, ",") > 0 Then item = Split(item, ",")

eric

Re,

Eric,

Génial. Une autre façon de faire tout aussi efficace. Il me faudra entrer dans la logique, regarder de plus près pour comprendre.

C'est juste impeccable. Merci encore.

Yeshua.

Plus efficace, tu conserves la vitesse des dictionaries dans les 2 cas.

Dans la recherche, mettre en premier dictionary celui dont la clé a le plus de chance d'être demandée.

Comme ça dans plus de 50% des cas tu ne rechercheras que dans celui là.

eric

Rechercher des sujets similaires à "gestion contenu dictionnaire comme fonction"