IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Modifier ordre de tri d'un SortedDictionary


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut Modifier ordre de tri d'un SortedDictionary
    Bonjour, j'ai créé un SortedDictionary (SD)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Friend Variables AsNew SortedDictionary(OfString, DonneesVariable)
    Je voudrai que l'ordre de tri ne soit pas "A1, A10, A2, B1, B10, ..." mais plutot "E1, E2, ..., E10, E11,..., A1, A2 ...".

    Pour vous expliquer l'origine de mon problème, au début j'utilisais un Dictionary dont l'ordre de création des clefs était bien: "E1, E2, ..., E10, E11,..., A1, A2 ...".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    PrivateSub InitialiseVariables()
    Dim MesTypeDonnee() AsString = {"E", "E", "EA", "EN", "EN", "A", "SA", "SN", "B", "R", "M", "V", "T", "C", "N"}
    Dim MonComptDepart() AsInteger = {0, 2000, 0, 0, 2000, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}
    Dim MonComptFin() AsInteger = {1023, 3023, 1020, 1008, 3008, 1023, 1020, 1008, 1023, 1023, 13823, 2046, 95, 95, 15}
    Dim MonComptStep() AsInteger = {1, 1, 4, 16, 16, 1, 4, 16, 1, 1, 1, 1, 1, 1, 1}
    Dim i, j AsInteger
    For j = 0 To 14
    For i = MonComptDepart(j) To MonComptFin(j) Step MonComptStep(j)
    Variables.Add(MesTypeDonnee(j) & i, New DonneesVariable("", "", False, False, "", "", ""))
    Next i
    Next j
    EndSub
    Ce qui fait que quand je l'utilisais, j'avais bien mes données (de type DonneesVariable qui est une structure à moi) dans l'ordre voulu lors du parcour de la collection par un For Each.

    Il s'avère que, contrairement à ce que je pensais, je suis obliger de créer quelques clefs supplémentaires après l'initialisation de mon Dictionary
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    MonAdresse = MonStreamReader.ReadLine
    IfNot Variables.ContainsKey(MonAdresse) Then
    Variables.Add(MonAdresse, New DonneesVariable("", "", False, False, "", "", ""))
    EndIf
    , et évidement ces clefs (qui sont alors créées en "fin" de dictionary) devraient se tourver au milieu de clefs déjà existantes.

    Je m'oriente donc vers un SD, mais ce n'est pas l'ordre alphabétique qui m'intéresse.

    Quelqu'un peut-il m'aider?



    Ce n'est pas parce que l'on allume la bougie de quelqu'un avec sa lanterne que l'on se prive de lumière.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Il faut que tu implémentes un IComparer<TKey> (TKey étant le type de la clé, string en l'occurence) dans lequel tu réalises la logique de tri (c'est à dire la méthode de comparaison des clés).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Public Class MyComparer
        Implements IComparer(Of String)
     
        Function Compare (x As String, y As String) As Integer
            ' La logique de comparaison ici
            ' Renvoie -1 si x<y, 0 si x=y, 1 si x>y
        End Function
     
    End Class
    Ensuite tu passes une instance de cette classe en paramètre du constructeur du SD:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim sd as New SortedDictionary(Of String, DonneesVariable) (New MyComparer)

  3. #3
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut
    OK, je crée donc une "surcharge" de la comparaison pour lui faire faire le tri qui m'intéresse.
    Mais dans le X et le Y de ton exemple, à quoi correspondent le X et le Y?
    Est-ce que j'ai bien compris en partant du principe que je ne vais pas avoir à passer réellement un X et un Y et que c'est le "système" qui s'occupera de mettre une clef 1 et 2 dans la moulinette?


    Ce n'est pas parce que l'on allume la bougie de quelqu'un avec sa lanterne que l'on se prive de lumière.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    x et y correspondent aux éléments à comparer
    Lors du tri, le SD passera 2 clés à la fonction Compare, et effectuera le tri en fonction du résultat de leur comparaison.

  5. #5
    Expert confirmé
    Avatar de neguib
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 627
    Détails du profil
    Informations personnelles :
    Âge : 65
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 627
    Par défaut
    Bonjour sibama

    Comme tu n'as pas encore signalé ton souci comme [Résolu], je me propose de te fournir en exemple un extrait de code perso:

    Création d'un parseur de clés
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    Imports System.Text
    Class MyParserKeys
        Public Structure Key
            Public litteral As String
            Public numeric As String
        End Structure
        Public Function parser(ByVal key As String) As Key
            Dim k As New Key()
            Dim str1 As New StringBuilder()
            Dim str2 As New StringBuilder()
            For Each c As Char In key
                If Char.IsNumber(c) Then str2.Append(c) Else str1.Append(c)
            Next
            k.litteral = str1.ToString
            k.numeric = str2.ToString
            Return k
        End Function
    End Class
    Utilisation de MyParserKeys lors de la création de ma classe Comparer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    Public Class MyComparer
        Implements IComparer(Of String)
        Private Litterals As String() = {"E", "EA", "EN", "A", "SA", "SN", "B", "R", "M", "V", "T", "C", "N"}
     
        Public Function Compare(ByVal key1 As String, ByVal key2 As String) As Integer Implements IComparer(Of String).Compare
            Dim p As New MyParserKeys()
            Dim k1 As String = p.parser(key1).litteral
            Dim k2 As String = p.parser(key2).litteral
            If k1 = k2 Then
                Dim n1 As String = p.parser(key1).numeric
                Dim n2 As String = p.parser(key2).numeric
                Return n1.CompareTo(n2)
            Else
                Return Array.IndexOf(Litterals, k1).CompareTo(Array.IndexOf(Litterals, k2))
            End If
        End Function
    End Class
    Utilisation de MyComparer lors de la création de ma classe SortedDictionary
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Public Class MySortedDictionary
        Inherits SortedDictionary(Of String, DonneesVariable)
     
        Public Sub New()
            MyBase.New(New MyComparer())
        End Sub
    End Class
    J'ai fait un petit test pour vérifier, mais rien ne vaut ta propre vérification Alors nous attendons de tes nouvelles.

  6. #6
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut
    Merci pour ta réponse nserhani, ton code marche super bien, j'ai juste remplacé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Dim n1 As String = p.parser(key1).numeric
    Dim n2 As String = p.parser(key2).numeric
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Dim n1 As Integer = Cint(p.parser(key1).numeric)
    Dim n2 As Integer = Cint(p.parser(key2).numeric)
    pour avoir un ordre de tri numérique croissant.

    Ton code est super sympa, et utilise quelques instructions que je ne connaissais pas.

    Après la dernière réponse de Tomlev, j'avais imaginé ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    FriendClass MonOrdreTriVariables
    Implements IComparer(OfString)
    Private MonOrdre AsString() = {"E", "E", "EA", "EN", "EN", "A", "SA", "SN", "B", "R", "M", "V", "T", "C", "N"}
     
    FriendFunction Compare(ByVal key1 AsString, ByVal key2 AsString) AsIntegerImplements IComparer(OfString).Compare
    ' Remplace l'ordre de tri alphabétique par l'ordre définit dans MesTypeDonnee
    Dim k1() AsString = Split(DecomposerAdresse(key1), " ")
    Dim k2() AsString = Split(DecomposerAdresse(key2), " ")
    If k1(0) = k2(0) Then
    ReturnCInt(k1(1)).CompareTo(CInt(k2(1)))
    Else
    Return Array.IndexOf(MonOrdre, k1(0)).CompareTo(Array.IndexOf(MonOrdre, k2(0)))
    EndIf
    EndFunction
    FriendFunction DecomposerAdresse(ByVal adresse AsString) AsString
    ' Insert un espace entre les parties alphabétique et numérique de l'adresse
    If IsNumeric(Microsoft.VisualBasic.Mid(adresse, 2, 1)) Then
    DecomposerAdresse = adresse.Insert(1, " ")
    Else
    DecomposerAdresse = adresse.Insert(2, " ")
    EndIf
    EndFunction
    EndClass
    Mon code marche bien au coup par coup (avec un point d'arrêt) mais est tellement lent avec toutes les boucles du reste du prog que VB me rend la main au bout de 60s d'exécution.

    Quelqu'un peut-il m'expliquer pourquoi ce code est si lent et s'il y a moyen de l'accélérer (je suis à vrai dire un peu vexé que mon code que je trouvais super optimisé rame comme un malade....).



    Ce n'est pas parce que l'on allume la bougie de quelqu'un avec sa lanterne que l'on se prive de lumière.

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par sibama Voir le message
    Quelqu'un peut-il m'expliquer pourquoi ce code est si lent et s'il y a moyen de l'accélérer (je suis à vrai dire un peu vexé que mon code que je trouvais super optimisé rame comme un malade....)
    Je vois pas trop ce qui fait que c'est lent... peut-être le fait que tu crées pas mal d'instances de String, avec tes Split et autres Insert, alors que nserhani utilise des StringBuilder (plus optimisés pour construire des chaînes).

  8. #8
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut
    Bien, aprés avoir essayé 2 ou 3 bricolages sur mon code (j'aime vraiment pas être vexé), j'utilise le code de nserhani (encore merci à lui).

    Cependant le code que j'utilise reste malgrès tout plus lent que lorsque je ne surcharge pas le "compare".


    Mon raisonnement est alors le suivant:
    • lors de ma phase de création de Variables, un Dictionary est suffisant pour contenir mes clefs dans l'ordre voulu.
    • Pendant la phase suivante il se peut que j'ajoute quelques clefs à la fin qui doivent en fait se retrouver "classées"
    • Ensuite un dictionary est à nouveau suffisant.
    Est-il possible de déclarer Variables en Dictionary, de le "convertir" en SortedDictionary bricolé à ma sauce au moment des ajouts, puis de le re"convertir" en dictionary une fois le dernier ajout effectué?

    J'aurai ainsi la rapidité du Dictionary et les fonctionalités du SortedDictionary bricolé aux moments voulus, sans les 'inconvéniants' aux autres moments.

    Ma question est peut-être un peu capilotractée (tirée par les cheveux), mais bon on sait jamais...



    Ce n'est pas parce que l'on allume la bougie de quelqu'un avec sa lanterne que l'on se prive de lumière.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par sibama Voir le message
    J'aurai ainsi la rapidité du Dictionary et les fonctionalités du SortedDictionary bricolé aux moments voulus, sans les 'inconvéniants' aux autres moments.
    Of course !
    Dictionary et SortedDictionary ont tous les deux un constructeur qui prend en paramètre un IDictionary<TKey, TValue>, et cette interface est évidemment implémentée par les 2 classes... tu peux donc faire la "conversion" comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Dim dico As New Dictionary(Of String, DonneesVariable)
    ...
    Dim sorted As New SortedDictionary(Of String, DonneesVariable)(dico, New MonOrdreTriVariables())
    ...
     
    dico = New Dictionary(Of String, DonneesVariable)(sorted)
    ...

  10. #10
    Expert confirmé
    Avatar de neguib
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 627
    Détails du profil
    Informations personnelles :
    Âge : 65
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 627
    Par défaut
    Bonjour à chacun

    Je vois que ma proposition t'apporte pratiquement la solution à ton souci. Cependant, au vue des dernières remarques, je te soumet l'idée de n'utiliser que le Dictionary pour le traitement des données (ajouts, suppressions) et de n'utiliser le MySortedDictionary que lorsque c'est absolument nécessaire (par exemple lors d'un affichage des données). Dans ce cas il suffira d'apporter une modification du constructeur de MySortedDictionary :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Public Class MySortedDictionary
        Inherits SortedDictionary(Of String, DonneesVariable)
     
        Public Sub New(ByVal d As Dictionary(Of String, DonneesVariable))
            MyBase.New(d, New MyComparer())
        End Sub
    End Class
    Ensuite, tu pourras éventuellement l'utiliser ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ''' sachant que par exemple ton Dictionary s'appelle Variables
       Dim sorted As New MySortedDictionary(Variables)
    Puis s'ouvre à toi le choix de garder ton Dictionary non trié, ou bien de le trier à chaque mise à jour comme te l'a indiqué Tomlev par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Variables = New Dictionary(Of String, DonneesVariable)(sorted)
    J'espère que tu pourras enfin avoir une pleine satisfaction et mettre dans ce cas le tag à ta question

  11. #11
    Membre confirmé Avatar de sibama
    Profil pro
    Inscrit en
    Août 2008
    Messages
    150
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 150
    Par défaut
    Merci à tous, ça marche super bien.



    Ce n'est pas parce que l'on allume la bougie de quelqu'un avec sa lanterne que l'on se prive de lumière.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [DisplayTag] Garder l'ordre de tri +en-tête
    Par Fr@ncky dans le forum Taglibs
    Réponses: 6
    Dernier message: 14/05/2007, 14h13
  2. Réponses: 1
    Dernier message: 29/03/2006, 11h33
  3. [SQL2K]URGENT: récupérer jeu de caractères et ordre de tri ?
    Par webtheque dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 26/04/2005, 11h43
  4. Ordre des tris / fonction upper
    Par slylafone dans le forum Débuter
    Réponses: 7
    Dernier message: 18/01/2005, 17h53
  5. Réponses: 7
    Dernier message: 20/10/2004, 08h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo