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 :

Faire des recherches dans un List(Of List(Of T)) ?


Sujet :

VB.NET

  1. #1
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut Faire des recherches dans un List(Of List(Of T)) ?


    J'ai une liste de liste comme ceci (c'est un test):
    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
    25
    26
    27
    28
       Private Structure Test
            Sub New(ByVal pTypeSonde As String,
                    ByVal pVal As Decimal)
                TypeSonde = pTypeSonde
                Val = pVal
            End Sub
     
            Dim TypeSonde As String
            Dim Val As Decimal
        End Structure
     
        Sub Main()
            Dim liste As New List(Of List(Of Test))
            For i As Integer = 0 To 1
                liste.Add(New List(Of Test))
     
                For j As Integer = 0 To 5
                    liste(0).Add(New Test("S" & i + 1, j))
                Next
            Next
     
            Dim l As List(Of Test) = liste.FindAll(Function(x) x.Contains("S2"))
            For Each s As Test In l
                Console.WriteLine(s.TypeSonde)
            Next
     
            Pause()
        End Sub
    Sauf qu'il n'aime pas trop. J'aimerais avoir une solution, si elle existe, de pouvoir faire une recherche de ce type via le Framework. Est-ce possible ? Ou dois-je me créer ma propre fonction de recherche ?


    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  2. #2
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    Il va falloir expliquer un peu mieux le but recherché là.

    Déjà List.Contains attend un élément (donc un Test ici) et toi tu lui donnes une chaine ; ça peut être remplacé par un Find ou un FindIndex
    Ensuite FindAll doit retourner un List(Of List(Of Test)) et toi tu as donné seulement List(Of Test) comme type résultat ; là aussi si tu ne recherches qu'un élément Find devrait être utilisé.

    Sur un autre plan, qui n'a rien à voir avec le sujet, il faut aussi se méfier lorsqu'on utilise une structure (qui plus est mutable) au lieu d'une classe ; la "sémantique" de copie associé à celles-ci peut donner des résultats inattendus pour le développeur.

  3. #3
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par Sehnsucht Voir le message
    Il va falloir expliquer un peu mieux le but recherché là.

    Déjà List.Contains attend un élément (donc un Test ici) et toi tu lui donnes une chaine ; ça peut être remplacé par un Find ou un FindIndex
    Ensuite FindAll doit retourner un List(Of List(Of Test)) et toi tu as donné seulement List(Of Test) comme type résultat ; là aussi si tu ne recherches qu'un élément Find devrait être utilisé.

    Sur un autre plan, qui n'a rien à voir avec le sujet, il faut aussi se méfier lorsqu'on utilise une structure (qui plus est mutable) au lieu d'une classe ; la "sémantique" de copie associé à celles-ci peut donner des résultats inattendus pour le développeur.
    Oui je me suis peut-être un peu embrouillé moi-même mais ce que je cherche à faire, c'est construire une liste de type List(Of Test) donc chaque l'élément TypeSonde de la structure contient la chaîne S2. En attendant j'ai fait cette recherche par une fonction que j'ai écrite:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        Private Function ListFindAllBy_TypeSonde(ByRef l As List(Of List(Of DatesSurverses)), ByVal s As String) As List(Of DatesSurverses)
            Dim list As New List(Of DatesSurverses)
     
            For Each _l As List(Of DatesSurverses) In l
                For Each _t As DatesSurverses In _l
                    If _t.TypeSonde = s Then
                        list.Add(_t)
                    End If
                Next
            Next
     
            Return list
        End Function
    Tout ce que je voulais savoir, c'est si c'était faisable en natif.
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  4. #4
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Tout ce que je voulais savoir, c'est si c'était faisable en natif.
    Ça veut dire quoi en natif parce que là pour moi c'est du "natif" et c'est en gros le fonctionnement de FindAll à ceci près que FindAll ne "compresse" pas une liste de liste en simple liste.
    Après on peut très bien passer par Linq pour faire ceci.

    Détail ; le ByRef ne sert strictement à rien ici

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par Sehnsucht Voir le message
    Ça veut dire quoi en natif parce que là pour moi c'est du "natif" et c'est en gros le fonctionnement de FindAll à ceci près que FindAll ne "compresse" pas une liste de liste en simple liste.
    Après on peut très bien passer par Linq pour faire ceci.
    Directement par les fonctions de l'objet comme j'ai essayé de faire (Find ou FindAll) mais ma fonction me suffit finalement, j'essaie seulement d'éviter à chaque fois de réécrire la roue

    Citation Envoyé par Sehnsucht Voir le message
    Détail ; le ByRef ne sert strictement à rien ici
    Je sort du monde du Langage C, pour moi ByRef permet, comme le passage par pointeur de modifier certes mais aussi de passer une référence de la variable (ici la liste) et non une copie, j'évite ainsi tout le processus de copie de données qui est inutile. Ou je me trompe dans le mode de fonctionnement de VB ?
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  6. #6
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Directement par les fonctions de l'objet comme j'ai essayé de faire (Find ou FindAll) mais ma fonction me suffit finalement, j'essaie seulement d'éviter à chaque fois de réécrire la roue
    Oui ; la fonction en elle-même convient amplement ; après dans les méthodes de List(Of T) il n'y a rien qui permette de sortir des listes imbriquées ; donc à part la fonction faite à la mano ou Linq ... après tu pourrais te faire une méthode (d'extension) générique qui gère l'ensemble des cas de ce genre (sur le modèle de la méthode Enumerable.SelectMany utilisée avec/par Linq)
    Je joins tout de même mon code de test ; ça peut être utile (à toi ou de futurs lecteurs qui seraient plus intéressés par l'utilisation de Linq)
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    Structure Test
        ReadOnly Property TypeSonde As String
        ReadOnly Property Val As Decimal
     
        Sub New(typeSonde As String, val As Decimal)
            Me.TypeSonde = typeSonde
            Me.Val = val
        End Sub
     
        Overrides Function ToString() As String
            Return $"{{ TypeSonde : {TypeSonde} ; Val : {Val:N2} }}"
        End Function
    End Structure
     
     
    Sub Main()
        Dim source As New List(Of List(Of Test)) From {
            (Aggregate i In Enumerable.Range(1, 2)
                 From j In Enumerable.Range(0, 5)
                 Select New Test($"S{i}", j)
             Into ToList),
            New List(Of Test)
        }
     
        Dim resultLinqMethod = source.
                               SelectMany(Function(subList) subList.
                                                            FindAll(Function(item) item.TypeSonde = "S2")).
                               ToList
     
        ' Nearly the same thing with different syntax
        Dim resultLinqQuery = Aggregate subList In source
                                  From item In subList
                                  Where item.TypeSonde = "S2"
                                  Select item
                              Into ToList
     
        ' List(Of List(Of Test)
        Dim resultNative = source.
                           ConvertAll(Function(subList) subList.
                                                        FindAll(Function(item) item.TypeSonde = "S2"))
     
        Array.ForEach({resultLinqMethod, resultLinqQuery}, Sub(result)
                                                               result.ForEach(AddressOf Console.WriteLine)
                                                               Console.WriteLine()
                                                           End Sub)
     
        resultNative.ForEach(Sub(subList) subList.ForEach(AddressOf Console.WriteLine))
    End Sub


    Citation Envoyé par Franck.H Voir le message
    Je sort du monde du Langage C, pour moi ByRef permet, comme le passage par pointeur de modifier certes mais aussi de passer une référence de la variable (ici la liste) et non une copie, j'évite ainsi tout le processus de copie de données qui est inutile. Ou je me trompe dans le mode de fonctionnement de VB ?
    Un peu oui et ma remarque sur le fait d'utiliser une Structure précédemment va probablement dans le même sens.

    En C++ la seule différence entre une class et une struct c'est le niveau de visibilité par défaut ; en .Net c'est totalement différent ; une structure se rapprocherais plus d'un objet à sémantique de valeur alors qu'une classe serait plus à sémantique d'entité.

    Pour le passage de paramètre ; quand on "a" une instance d'une classe ; ce que l'on a réellement c'est une référence vers cette instance (là où avec une instance d'une structure c'est réellement l'instance/la valeur que l'on "détient")
    Du coup là tu passes une pointeur sur pointeur (si je reprends une terminologie C)
    En utilisant ByVal (qu'il n'est plus obligatoire de mentionner, c'est implicite si on l'omet [selon la version du framework/de visual studio que tu utilises]) on passe une copie certes ; mais une copie d'une référence reste une référence vers le même objet ; par contre en utilisant ByRef on passe directement la référence et donc on peut réassigner celle-ci à une nouvelle instance

    J'illustre parce que je ne suis pas forcément clair
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    Class SomeClass
        Public Property Value As Integer
    End Class
     
    Structure SomeStruct
        Public Property Value As Integer
    End Structure
     
     
    Module Program
        Sub MutateByVal(arg As SomeClass)
            Console.WriteLine($"Given : {arg.Value}")
            arg.Value += 1
            Console.WriteLine($"Mutated : {arg.Value}")
        End Sub
     
        Sub MutateByRef(ByRef arg As SomeClass)
            Console.WriteLine($"Given : {arg.Value}")
            arg.Value += 1
            Console.WriteLine($"Mutated : {arg.Value}")
        End Sub
     
        Sub ReassignByVal(arg As SomeClass)
            Console.WriteLine($"Given : {arg.Value}")
            arg = New SomeClass With {.Value = 42}
            Console.WriteLine($"Reassigned : {arg.Value}")
        End Sub
     
        Sub ReassignByRef(ByRef arg As SomeClass)
            Console.WriteLine($"Given : {arg.Value}")
            arg = New SomeClass With {.Value = 42}
            Console.WriteLine($"Reassigned : {arg.Value}")
        End Sub
     
        Sub MutateByVal(arg As SomeStruct)
            Console.WriteLine($"Given : {arg.Value}")
            arg.Value += 1
            Console.WriteLine($"Mutated : {arg.Value}")
        End Sub
     
        Sub MutateByRef(ByRef arg As SomeStruct)
            Console.WriteLine($"Given : {arg.Value}")
            arg.Value += 1
            Console.WriteLine($"Mutated : {arg.Value}")
        End Sub
     
        Sub ReassignByVal(arg As SomeStruct)
            Console.WriteLine($"Given : {arg.Value}")
            arg = New SomeStruct With {.Value = 42}
            Console.WriteLine($"Reassigned : {arg.Value}")
        End Sub
     
        Sub ReassignByRef(ByRef arg As SomeStruct)
            Console.WriteLine($"Given : {arg.Value}")
            arg = New SomeStruct With {.Value = 42}
            Console.WriteLine($"Reassigned : {arg.Value}")
        End Sub
     
        Sub Main()
            Dim classItem As New SomeClass
            Console.WriteLine("Start Class")
            Console.WriteLine("-----------")
            Console.WriteLine($"Before {NameOf(MutateByVal)} : {classItem.Value}")
            MutateByVal(classItem)
            Console.WriteLine($"After {NameOf(MutateByVal)} : {classItem.Value}")
            Console.WriteLine()
            Console.WriteLine($"Before {NameOf(MutateByRef)} : {classItem.Value}")
            MutateByRef(classItem)
            Console.WriteLine($"After {NameOf(MutateByRef)} : {classItem.Value}")
            Console.WriteLine()
            Console.WriteLine($"Before {NameOf(ReassignByVal)} : {classItem.Value}")
            ReassignByVal(classItem)
            Console.WriteLine($"After {NameOf(ReassignByVal)} : {classItem.Value}")
            Console.WriteLine()
            Console.WriteLine($"Before {NameOf(ReassignByRef)} : {classItem.Value}")
            ReassignByRef(classItem)
            Console.WriteLine($"After {NameOf(ReassignByRef)} : {classItem.Value}")
            Console.WriteLine()
     
            Console.WriteLine()
            Dim structItem As New SomeStruct
            Console.WriteLine("Start Struct")
            Console.WriteLine("-----------")
            Console.WriteLine($"Before {NameOf(MutateByVal)} : {structItem.Value}")
            MutateByVal(structItem)
            Console.WriteLine($"After {NameOf(MutateByVal)} : {structItem.Value}")
            Console.WriteLine()
            Console.WriteLine($"Before {NameOf(MutateByRef)} : {structItem.Value}")
            MutateByRef(structItem)
            Console.WriteLine($"After {NameOf(MutateByRef)} : {structItem.Value}")
            Console.WriteLine()
            Console.WriteLine($"Before {NameOf(ReassignByVal)} : {structItem.Value}")
            ReassignByVal(structItem)
            Console.WriteLine($"After {NameOf(ReassignByVal)} : {structItem.Value}")
            Console.WriteLine()
            Console.WriteLine($"Before {NameOf(ReassignByRef)} : {structItem.Value}")
            ReassignByRef(structItem)
            Console.WriteLine($"After {NameOf(ReassignByRef)} : {structItem.Value}")
        End Sub
     
    End Module
    Output :
    Start Class
    -----------
    Before MutateByVal : 0
    Given : 0
    Mutated : 1
    After MutateByVal : 1

    Before MutateByRef : 1
    Given : 1
    Mutated : 2
    After MutateByRef : 2

    Before ReassignByVal : 2
    Given : 2
    Reassigned : 42
    After ReassignByVal : 2

    Before ReassignByRef : 2
    Given : 2
    Reassigned : 42
    After ReassignByRef : 42


    Start Struct
    -----------
    Before MutateByVal : 0
    Given : 0
    Mutated : 1
    After MutateByVal : 0

    Before MutateByRef : 0
    Given : 0
    Mutated : 1
    After MutateByRef : 1

    Before ReassignByVal : 1
    Given : 1
    Reassigned : 42
    After ReassignByVal : 1

    Before ReassignByRef : 1
    Given : 1
    Reassigned : 42
    After ReassignByRef : 42


    On voit bien qu'avec une classe (donc quand on détient une référence vers l'objet) les modifications sont répercutées à l'appelant aussi bien ByVal (on donne une copie de la référence) que ByRef (on donne directement la référence).
    Par contre la réassignation ne se répercute que si c'est passé ByRef (sinon on réassigne juste la copie de la référence à autre chose mais la référence originelle elle n'a pas été réassignée)

    De même on voit bien qu'avec une structure (donc quand on détient l'objet lui-même) les modifications et réassignations ne sont pas répercutées à l'appelant lors d'un appel ByVal (parce qu'on ne fait que modifier/réassigner la copie de l'objet pas l'objet lui-même) alors qu'avec Byref ça fonctionne (vu que là on a passé une référence vers cet objet).

    Voilà j'espère que c'est un peu plus clair ; il y a sans doute quelques imprécisions, je ne suis pas un expert et ça reste de la vulgarisation

  7. #7
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Ok parfait, merci pour ton aide et tes explications
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

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

Discussions similaires

  1. Faire des recherches dans plusieur Feuilles
    Par edpth dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 17/11/2009, 00h21
  2. Réponses: 1
    Dernier message: 28/05/2008, 23h03
  3. [XPATH] génération d'un xpath pour faire des recherches dans un xml
    Par Spaceman Spiff dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 11/06/2007, 18h18
  4. Que faut il utiliser pour faire des recherches dans LDAP?
    Par kabouns dans le forum API standards et tierces
    Réponses: 5
    Dernier message: 04/08/2006, 15h24
  5. [HTML] faire des tabulation dans une liste <select>
    Par renofx1 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 20/01/2006, 23h36

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