Alternative aux Structures [Résolu]

Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
- - Dernière réponse : CGSI3
Messages postés
417
Date d'inscription
vendredi 22 février 2008
Statut
Membre
Dernière intervention
7 janvier 2018
- 13 mars 2011 à 19:24
Bonjour à tous,
c'est la premiere fois que je poste pour vous demandez votre aide.
Jusque là j'utilisais les sructures pour déclarer mes variables du type :
[i]Structure Personne
Public Nom as string
Public Age as String
End Structure/i

Ensuite je déclare un tableau de personne :
Public Personnes () as Personne

Puis je peux utiliser mon tableau :
Personnes (0).Nom = "Durand"
Personnes (0).Age = 40

Problème : si je supprime "Durand", cela laisse une case vide dans mon tableau et m'oblige à decaler toutes les entrées aprés l'Entrée "Durand".

J'ai des vagues notion d'objet et de collections mais je ne sais pas du tout si c'est une meilleure solution ni comment la mettre en oeuvre.

Je vous remercie d'avance pour faire partager votre experience....
Afficher la suite 

Votre réponse

20 réponses

Meilleure réponse
Messages postés
423
Date d'inscription
vendredi 17 novembre 2006
Statut
Membre
Dernière intervention
15 juillet 2014
7
3
Merci
Voili voilou,

Par contre j'ai remplacé la structure Personne par la classe Personne, ce qui résout tous vos problèmes et est bien plus adapté à ce que vous cherchez à faire. Vous verrez que la différence de conception avec la structure n'est pas si ennorme comparé au fait qu'elle vous facilite la vie dans votre cas.

Imports System.Collections.Generic
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO

<Serializable()> _
Public Class Personne

    Private _nom As String
    Private _prenom As String
    Private _age As Integer

    Public Property Nom As String
        Get
            Return _nom
        End Get
        Set(ByVal value As String)
            _nom = value
        End Set
    End Property

    Public Property Prenom As String
        Get
            Return _prenom
        End Get
        Set(ByVal value As String)
            _prenom = value
        End Set
    End Property

    Public Property Age As Integer
        Get
            Return _age
        End Get
        Set(ByVal value As Integer)
            _age = value
        End Set
    End Property

    Public Sub New(ByVal nom As String, ByVal prenom As String, ByVal age As Integer)
        _nom = nom
        _prenom = prenom
        _age = age
    End Sub

End Class

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim formatter As New BinaryFormatter()
        Dim personnes As New SortedList(Of String, Personne)
        Dim unePersonne As Personne

        'Création d'une personne
        unePersonne = New Personne("Durant", "Pierre", 30)

        'Ajout de la personne à la liste
        personnes.Add(unePersonne.Nom, unePersonne)
        'ou directement
        personnes.Add("Dupond", New Personne("Dupond", "Jacques", 20))

        'Accès à l'age d'une personne
        Console.WriteLine("L'age de Mr. Durant est {0}", personnes("Durant").Age)

        'Modification de l'age d'une personne
        personnes("Dupond").Age = 22

        'Modification du nom d'une personnes
        unePersonne = personnes("Durant")
        personnes.Remove("Durant")
        unePersonne.Nom = "Durand"
        personnes.Add(unePersonne.Nom, unePersonne)

        'Sérialization de la liste de personnes
        Using fs As New FileStream("C:\maListe", FileMode.Create, FileAccess.Write)
            formatter.Serialize(fs, personnes)
        End Using

        'Déserialization de la liste de personnes
        Dim personnesDeserialize As SortedList(Of String, Personne)
        Using fs As New FileStream("C:\maListe", FileMode.Open, FileAccess.Read)
            personnesDeserialize = TryCast(formatter.Deserialize(fs), SortedList(Of String, Personne))
        End Using

        If (personnesDeserialize IsNot Nothing) Then

            'Iteration de la liste des personnes déserializée
            For Each kvp As KeyValuePair(Of String, Personne) In personnesDeserialize
                Console.WriteLine("Clé unique {0} ; Nom {1} ; Prénom = {2} ; Age = {3}", _
                                  kvp.Key, _
                                  kvp.Value.Nom, _
                                  kvp.Value.Prenom, _
                                  kvp.Value.Age)
            Next

            'Suppression d'une personne
            personnesDeserialize.Remove("Dupond")

        Else
            Console.WriteLine("Le fichier 'C:\maListe' n'est pas une liste de personnes valide")
        End If

    End Sub


Si vous avez des questions par rapport à la classe Personne, n'ésitez pas.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 131 internautes nous ont dit merci ce mois-ci

Commenter la réponse de foliv57
Messages postés
423
Date d'inscription
vendredi 17 novembre 2006
Statut
Membre
Dernière intervention
15 juillet 2014
7
3
Merci
Bien sur, une fois déserializé, vous pouvez utiliser l'objet normalement. Le fait d'avoir créer une nouvelle variable personnesDeserialize et de l'avoir utilisé pour lister les personnes dans la console n'est qu'un exemple.

Vous pouvez même très bien, dans mon exemple, déserializer directement en utilisant la variable 'personnes'

'Déserialization de la liste de personnes
Using fs As New FileStream("C:\maListe", FileMode.Open, FileAccess.Read)
  personnes = TryCast(formatter.Deserialize(fs), SortedList(Of String, Personne))
End Using

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 131 internautes nous ont dit merci ce mois-ci

Commenter la réponse de foliv57
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Modérateur
Dernière intervention
11 avril 2018
267
0
Merci
Bonjour,

si je supprime "Durand", cela laisse une case vide dans mon tableau et m'oblige à decaler toutes les entrées aprés l'Entrée "Durand".

le mieux serait bien évidemment d'utiliser une base de données
Mais si tu veux continuer à utiliser un tableau dynamique typé comme ta structure, rien ne t'en empêche. Et tu n'as alors pas l'obligation, en cas de suppression d'un élément de ton tableau, de "tout décaler" !
Question de méthode :
1) tu substitues à l'élément supprimé le dernier élément de ton tableau
2) tu redimensionnes ton tableau à son ubound - 1
Comme dans l'affaire du sapeur camembert et de ses trous dans la cour de sa caserne
Voilà !



____________________
Vous aimez Codes-Sources ? Il vous aide ? Cliquez ici pour l'aider à continuer
Cliquer sur "Réponse acceptée" en bas d'une solution adéquate est
Commenter la réponse de ucfoutu
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Merci pour cette réponse rapide et cette technique astucieuse, c'est effectivement une methode simple que je pourrais utiliser dans mon projet....
mais j'ai aussi oublier un détail...si on veux retrouver un element il faut parcourir tous le tableau.....je me demandais aussi si il n'y a pas plus efficace et comment vous procederiez.....sachant que si je souhaite retrouver un element par sa proriété Nom (l'exemple est mal choisi, j'aurais du parler du numéro de securité sociale plutôt qui lui est unique mais ce n'est qu'un exemple)
Commenter la réponse de BasicZx81
Messages postés
417
Date d'inscription
vendredi 22 février 2008
Statut
Membre
Dernière intervention
7 janvier 2018
2
0
Merci
Bonjour BasicZX81,

Une idée ...

"Hashtable" et ContainsKey (juste pour une collection de paires clé/valeur )
http://msdn.microsoft.com/fr-fr/library/system.collections.hashtable(v=vs.80).aspx

Efficace pour la recherche, l'ajout et la suppression, (add & remove) mais limité a clé/valeur .
Mais je ne sais pas trop si cela répond a tes attentes!
Cordialement CGSI3
Commenter la réponse de CGSI3
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Bonjour GSI3,
C'est un peu l'idée mais la Hashtable se limite à 2 colonnes (clé/valeur)....
dans mon exemple je me suis arreté à "Nom" et "Age" mais il y a davantage de colonnes....

J'ai essaiyé de créer des objets dans une collection pour pouvoir utiliser la methode Indexof mais la méthode attant un objet du type Personnes(x), mais je souhaite acceder à l'element non pas avec "x" mais avec "Nom" qui je rappele est unique (mon exemple est mal choisi)....
Commenter la réponse de BasicZx81
Messages postés
417
Date d'inscription
vendredi 22 février 2008
Statut
Membre
Dernière intervention
7 janvier 2018
2
0
Merci
ReBonjour BasicZX81,

j'ai récement utilisé un tableau d'élément "structure" et en parallele ce type "HashTable" en l'initialisant "par ligne" avec l'identifiant "Nom" et l' "Indice" de la ligne dans le tableau.
Tu peux ensuite utiliser les fonctions de la hashtable. (recherche, tri etc)
Et retrouver la ligne X dans le tableau tres rapidement selon le nom ...
Idem pour trier rapidement un tableau sur un seul parametre

(Je parle du nom ou d'une clé représentant l'individu genre Nom + Prenom + Age etc ...)

c'est une piste simple possible

Sinon beaucoup plus pro et compliqué ...:

http://msdn.microsoft.com/fr-fr/library/system.collections.collectionbase(v=VS.80).aspx

Voici le commentaire:
Cette classe de base facilite aux implémenteurs la création d'une collection personnalisée fortement typée. Il est préférable d'étendre cette classe de base plutôt que d'en créer une nouvelle.

Mais malheureusement je ne m'y suis pas encore frotté ...
Bonne Prog CGSI3
Commenter la réponse de CGSI3
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Merci pour ta réponses CGSI3,
J'ai effectivement explorer ta methode avec gestion d'une double table....la premiere table me servant à indexer mes données de facon à retrouver un objet rapidement et la seconde pour stocker mes objets.....mais cela s'avere un peu fastidieux à utiliser dans mon code....donc je continue les structures pour le moment....

Cela dit ca peux être une trés bonne idée d'implémenter ça dans une classe pour simplifier son utilisation mais hélas je ne sais pas implementer correctement les classes.....Je jetterrais un oeuil sur le lien que tu propose ca peux effectivement m'interresser.....

Merci beaucoup.....
Commenter la réponse de BasicZx81
Messages postés
423
Date d'inscription
vendredi 17 novembre 2006
Statut
Membre
Dernière intervention
15 juillet 2014
7
0
Merci
Bonjour,

Voici une facon de faire possible :

Public Structure Personne
  Public Prenom as String
  Public Age as Integer

  Public Sub New(ByVal prenom as String, ByVal Age as Integer)
    Me.Prenom = prenom
    Me.Age = age
  End Sub

End Structure

Public Sub Toto()
  Dim personnes as New System.Collections.Generic.SortedList(Of String, Personne)
  
  'Ajout
  personnes.Add("Durant", new Personne("Pierre", 30))

  'Utilisation
  Console.WriteLine("Prénom de Mr.Durant = ", personnes("Durant").Prenom)
  Console.WriteLine("Agede Mr.Durant = ", personnes("Durant").Age)

  'Par contre le nom étant unique, pour le modifier il faudra faire
  Dim durant as Personne = personnes("Durant")
  personnes.Remove("Durant")
  personnes.Add("Durand", durant)

  'Suppression
  personnes.Remove("Durant")

End Sub

Commenter la réponse de foliv57
Messages postés
423
Date d'inscription
vendredi 17 novembre 2006
Statut
Membre
Dernière intervention
15 juillet 2014
7
0
Merci
Et, au cas ou, pour parcourir toute la liste :
For Each personne as System.Collections.Generic.KeyValuePair(Of String, Personne) In personnes
  Console.WriteLine("Nom {0} ; Prénom {1} ; Age = {2}", personne.Key, personne.Value.Prenom, personne.Value.Age)
Next
Commenter la réponse de foliv57
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Merci beaucoup foliv57 pour cette derniere proposition.....Il va falloir que j'analyse le comportement de cette methode plus en détail, ca à l'air trés simple et efficace....c'est peut-être exactement ce que je cherchais.....
Avec tout mes remerciements....
Commenter la réponse de BasicZx81
Messages postés
417
Date d'inscription
vendredi 22 février 2008
Statut
Membre
Dernière intervention
7 janvier 2018
2
0
Merci
Idem ... Tres ingenieux comme manière de faire
Merci beaucoup pour ton Post.
Commenter la réponse de CGSI3
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Désolé, je pensais en avoir fini avec ce post mais j'en encore une question.
Je m'apercois que l'on ne pas deserializer une structure (ou du moins trés diffilement)...est ce que la solution proposé par Foliv57 peut me permettre de serializer/deserializer facilement ?
Par avance je vous remercie beaucoup.
Commenter la réponse de BasicZx81
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Bonjour,
J'ai effectué des essais avec la méthode de Foliv57, je rencontre 2 problèmes :

1 - Pour assigner une valeur du style :
personnes("Durant").Age = 30 'Ca ne marche pas

2 - Pour sérialiser les données
Avec la méthode de Foliv57 ou en utilisant des structures classique, lorsque je veux déserializer j'obtiens un message : Le cast n'est pas valide ! Ca veux dire quoi et comment régler ce problème...

PS : J'aimerais beaucoup pouvoir structurer mes donner comme le propose Foliv57....aprés tous les essais que j'ai fait ca me parait être une méthode trés efficace si j'arrive à résoudre ces 2 points.....
Merci beaucoup pour votre aide....
Commenter la réponse de BasicZx81
Messages postés
423
Date d'inscription
vendredi 17 novembre 2006
Statut
Membre
Dernière intervention
15 juillet 2014
7
0
Merci
1 - Pour assigner une valeur du style :
personnes("Durant").Age = 30 'Ca ne marche pas


Désolé, j'ai écrit l'exemple sans visual studio et j'avais completement oublié qu'on ne pouvait pu affecter un membre d'une structure dans une collection, donc qu'il faut réaffecter toute la structure ex :
personnes("Durant") = New Personne(personnes("Durant").Prenom, 30)


Mais du coup cela rend la solution disgracieuse.

J'ai réinstallé un VB express, je vous prépare un exemple qui tien la route avec la sérialisation.
Commenter la réponse de foliv57
Messages postés
417
Date d'inscription
vendredi 22 février 2008
Statut
Membre
Dernière intervention
7 janvier 2018
2
0
Merci
Bonjour a vous deux,
En attendant, cette solution marche mais est loin d'être propre

Dim P As Personne = personnes.Item("Durant")
P.Age = 30
personnes.Item("Durant") = P

Il y a surement mieux ....
Commenter la réponse de CGSI3
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Merci CGSI3 et Foliv57....
Je ne pourrais tester que ce soir c'est ta proposition Foliv57 à l'air de vraiment tenir la route...Je te remercie infiniment pour tes efforts. Par contre à Priori tu dezerialise les données pour les affichées sur la console, est ce que on peux deserializer pour recharger les données dans la collection 'Personnes' ?
Merci beaucoup si vous pouvez répondre à cette derniere petite question...j'espère.
Commenter la réponse de BasicZx81
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Merci beaucoup Foliv57, Tous ce ci me parait excellent, j'essaye tous ca dès ce soir. Si tous fonctionne comme prevus je pense que c'est un modèle de structuration des données que je généraliserais quasiment dans toutes mon appli....Merci beaucoup pour votre aide.
Commenter la réponse de BasicZx81
Messages postés
140
Date d'inscription
samedi 5 mars 2011
Statut
Membre
Dernière intervention
13 août 2013
0
Merci
Bonsoir à tous, le code de Foliv57 que je remercie beaucoup fonctionne parfaitement, pour ceux que ca interresse je rajouterais 2 instructions qui pourront être utile à certains d'entres vous ou au débutant.

'Indique le nombre de personne
MsgBox(personnes.Count)

'Controle obligatoire avant création d'une personne pour ne pas générer une erreur :
If personnes.ContainsKey("Dupond") Then MsgBox("la Personne existe déja ")

Cordialement.
Commenter la réponse de BasicZx81
Messages postés
417
Date d'inscription
vendredi 22 février 2008
Statut
Membre
Dernière intervention
7 janvier 2018
2
0
Merci
Grand merci a vous deux,
très efficace comme code !
Bonne soirée
CGSI3
Commenter la réponse de CGSI3

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.