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 :

[LINQ] Vérifier si deux listes ont des éléments en commun.


Sujet :

VB.NET

  1. #1
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut [LINQ] Vérifier si deux listes ont des éléments en commun.
    Hello,

    Je pose le problème. Disons que nous avons la classe suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Public Class MyClass
        Public Property Id As Integer
        Public Property List As List(Of Integer)
     
        'peu importe le reste de la classe
    End Class
    Si on a une liste de type List(Of MyClass), comment s'assurer que, pour chaque instance de MyClass dans notre liste, leur liste de type List(Of Integer) n'ont pas d'élément en commun.

    Je pensais faire cela en Linq mais j'ai du mal...
    Mon idée étant d'ajouter un propriété à MyClass pour marquer les instances à problèmes. Une fois les instances de MyClass qui posent problèmes repérées, je peux les colorer/mettre en erreur/etc. facilement dans le DataGridView qui les affiche pour l'utilisateur.

    Voici où j'en suis :
    Code vb : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Dim myList As List(Of MyClass)
    'remplissage de la liste, peu importe comment
     
    'selection des instances qui posent problèmes
    Dim data = (From i As MyClass In myList
                     Join j as MyClass In myList on Not i.Id Equals j.Id
                     'il manque quelque chose ici pour faire la comparaison des deux listes d'entiers...
                     Select i)
     
    'marquage de ces instances
    For Each elem as MyClass In data.ToList
        elem.IsError = True
    Next

    Quelqu'un aurait-il une idée ? Peut-être aussi que je fais fausse route avec Linq. Si vous avez un autre moyen plus efficace, je suis preneur bien sûr.

    Merci d'avance.

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    j'aurais tenté un truc du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dim r = (from m1 in mylist from m2 in mylist where m1 isnot m2 and m1.ids.intersect(m2.ids).count > 0 select new with {.instance1 = m1, .instance2 = m2})
    mais pas sur que ca soit bon ^^
    enfin au moins tu as le .intersect (sort une liste avec que ce qui est identique) et le .count>0 qui dit s'il y en a
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Ah je ne connaissais pas le intersect !

    Vais tester cela de suite

    EDIT
    J'avais tenté de simplier/généraliser l'exemple. Ca marche aussi si à la place d'une liste d'entier j'ai une liste d'une autre classe custom ? J'imagine qu'il va falloir que cette 2e classe custom implémente une interface du genre IComparable non ?

    EDIT 2
    Il faut effectivement implémenter IEqualityComparer(Of T) si j'ai bien compris la MSDN.
    Je passe la discussion en résolu. Il n'y a pas de raison que cela ne fonctionne pas .

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    pour un type par valeur, ca doit être = qui est utilisé (integer et autre)
    pour un type par référence, ca doit être Is qui est utilisé (classe, pointeur identique)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    pour un type par valeur, ca doit être = qui est utilisé (integer et autre)
    pour un type par référence, ca doit être Is qui est utilisé (classe, pointeur identique)
    Oui, ça c'est le comparateur par défaut. Mais dans mon cas, ce n'est pas bon car vu qu'il s'agit d'une classe custom, c'est évidemment un type par référence mais en plus, ce sont à chaque fois des instances différentes chez moi car chaque objet va récupérer "lui-même" sa liste d'objet dans la DB. Du coup, on se retrouve avec des listes qui pourrait contenir des objets identiques mais dans des instances bien séparées. Le Is n'est alors pas utilisable si j'ai bien tout compris car l'opérateur Is regarde si les deux objets sont bien stockées au même endroit en mémoire. Si oui, ils sont identiques.

    Du coup, ma classe doit implémenter IEqualityComparer(Of T) histoire que .NET sache comment déterminer si deux objets du type T sont identiques.

    Ca va ? Je n'écris pas trop de conneries ? ^^

  6. #6
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    ca doit être ca oui
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  7. #7
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut un dernier détail...
    ...à propos de IEqualityComparer(Of T).GetHashCode qu'il faut définir pour implémenter l'interface.

    De ce que j'ai compris, cette méthode doit retourner un entier unique pour chaque objet unique. Du coup, si mon objet à un Id, il suffit juste que je retourne cet Id ?

    Ca m'a l'air trop simple pour être vrai .

  8. #8
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    et pourtant ca me semble bon

    mais comme je pensais au début, si tu as des id, .intersect convient sans implémenter cette interface

    et dans le code que je t'ai proposé l'intersect est fait sur les integer
    sinon j'aurais évoqué le fait qu'il faut que les références soient les mêmes (ce qui se fait des fois, car quand on y pense, si tu as 2 instances avec la même chose dedans, pourquoi avoir 2 instances ? ^^)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  9. #9
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    et pourtant ca me semble bon

    mais comme je pensais au début, si tu as des id, .intersect convient sans implémenter cette interface
    Euh... Il y a une propriété nommée Id dans la 2e classe custom (dans la 1e aussi mais on s'en fout en fait) mais je ne vois pourquoi VS irait d'office prendre une telle propriété pour faire la comparaison.
    Ok, c'est un standard et tant qu'on reste "logique", ça va marcher dans 99% des cas.

    Mais d'un point de vue purement théorique, rien ne m'interdit d'avoir une propriété Id de type String et un propriété Desc de type Integer et de mettre une description dans Id et un identifiant dans Desc...

    Je flagellerai bien sûr personnellement le collègue qui me fera un jour une énormité pareille mais ça fonctionnera.

    En bref, je ne comprends pas ta remarque.

  10. #10
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    au temps pour moi, j'ai du mal lire ta classe
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  11. #11
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    au temps pour moi, j'ai du mal lire ta classe
    L'exemple de code que j'ai donné au tout début était simplifié pour pas se prendre le chou.

  12. #12
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    non en fait j'ai du bien lire

    enfin si tu veux comparer les list(of integer) des instances, c'est bien des integer donc intersect direct

    non ?
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  13. #13
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    non en fait j'ai du bien lire

    enfin si tu veux comparer les list(of integer) des instances, c'est bien des integer donc intersect direct

    non ?
    T'as sûrement pas vu ma réponse le temps de poster ce message-ci mais ça fait rien. Voici quand même le code de la vraie classe que je cherche à comparer.
    N.B. : La liste d'entier de l'exemple du début est la propriété Seasons ici.
    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
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    Public Class PromoDetailOwn
        Inherits PromoDetail
     
        Public Property Department As Department
        Public Property Brand As Brand
        Public Property Seasons As List(Of Season)
        Public Property SeasonsRange As String
     
        'Public Sub New(id As Integer, buyingDept As BuyingDept, comment As String, note As String, priceReduction As Boolean, percentage As Decimal, encoded As Boolean, dept As Department, brand As Brand)
        Public Sub New(id As Integer, buyingDept As BuyingDept, desc As String, note As String, percentage As Decimal, listtype As String, dept As Department, brand As Brand, percentType As PercentType, encoded As Boolean, attachement As Attachment, isduplicate As Boolean, isnew As Boolean)
            'MyBase.New(id, buyingDept, comment, note, priceReduction, percentage, encoded)
            MyBase.New(id, buyingDept, desc, note, percentage, listtype, percentType, encoded, attachement, isnew)
            Me.Department = dept
            Me.Brand = brand
            Me.SeasonsRange = ""
            Me.Seasons = New List(Of Season)
            Me.IsDuplicate = isduplicate
        End Sub
     
        Public Sub New(id As Integer, buyingDept As BuyingDept, desc As String, note As String, percentage As Decimal, listtype As String, dept As Department, brand As Brand, percentType As PercentType, encoded As Boolean, isnew As Boolean)
            'MyBase.New(id, buyingDept, comment, note, priceReduction, percentage, encoded)
            MyBase.New(id, buyingDept, desc, note, percentage, listtype, percentType, encoded, isnew)
            Me.Department = dept
            Me.Brand = brand
            Me.SeasonsRange = ""
            Me.Seasons = New List(Of Season)
        End Sub
    End Class
     
    Public Class PromoDetail
        Implements DtoBase
     
        Public Property Isnew As Boolean Implements DtoBase.Isnew
     
        Public Property Id As Integer 'DTD_ID pour demo et DTO_ID pour ferme
        Public Property BuyingDepartment As BuyingDept
        Public Property Description As String
        Public Property Note As String
        'Public Property PriceReduction As Boolean
        Public Property Percentage As Decimal
        Public Property PercentType As PercentType
        Public Property Encoded As Boolean
        Public Property Attachment As Attachment
        Public Property IsDuplicate As Boolean
        Public Property ErrorText As String
     
        Private _listType As String
        Public ReadOnly Property ListType As String
            Get
                Return _listType
            End Get
        End Property
        Private _productCount As Integer
        Public ReadOnly Property ProductCount As Integer
            Get
                Return _productCount
            End Get
        End Property
     
        Private _products As List(Of Product)
        Public Property Products As List(Of Product)
            Get
                Return _products
            End Get
            Set(value As List(Of Product))
                _products = value
                If value.Count > 0 Then
                    _listType = "INC"
                    _productCount = value.Count
                End If
            End Set
        End Property
     
        Private _productsOut As List(Of Product)
        Public Property ProductsOut As List(Of Product)
            Get
                Return _productsOut
            End Get
            Set(value As List(Of Product))
                _productsOut = value
                If value.Count > 0 Then
                    _listType = "EXC"
                    _productCount = value.Count
                End If
            End Set
        End Property
     
        'Public Sub New(id As Integer, buyingDept As BuyingDept, comment As String, note As String, priceReduction As Boolean, percentage As Decimal, encoded As Boolean)
        Public Sub New(id As Integer, buyingDept As BuyingDept, desc As String, note As String, percentage As Decimal, listtype As String, percentType As PercentType, encoded As Boolean, attachement As Attachment, isnew As Boolean)
            Me.Id = id
            Me.BuyingDepartment = buyingDept
            Me.Description = desc
            Me.Note = note
            'Me.PriceReduction = priceReduction
            Me.Percentage = percentage
            Me.PercentType = percentType
            Me.Encoded = encoded
            Me._listType = listtype
            Me.Attachment = attachement
            Me.Isnew = isnew
        End Sub
     
        Public Sub New(id As Integer, buyingDept As BuyingDept, desc As String, note As String, percentage As Decimal, listtype As String, percentType As PercentType, encoded As Boolean, isnew As Boolean)
            Me.Id = id
            Me.BuyingDepartment = buyingDept
            Me.Description = desc
            Me.Note = note
            'Me.PriceReduction = priceReduction
            Me.Percentage = percentage
            Me.PercentType = percentType
            Me.Encoded = encoded
            Me._listType = listtype
            Me.Isnew = isnew
        End Sub
    End Class
    Et la classe Season pour avoir la totale :
    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
    Public Class Season
        Implements DtoBase, IEqualityComparer(Of Season)
     
        Public Property Id As Integer
        Public Property Code As Short
        Public Property Description As String
        Public Property Year As Short
     
        Public Sub New(id As Integer, code As Integer, description As String, year As Short, isnew As Boolean)
            Me.Id = id
            Me.Code = code
            Me.Description = description
            Me.Year = year
            Me.Isnew = isnew
        End Sub
     
        Public Property Isnew As Boolean Implements DtoBase.Isnew
     
        Public Overrides Function ToString() As String
            Return Me.Description
        End Function
     
        Public Function Equals1(x As Season, y As Season) As Boolean Implements IEqualityComparer(Of Season).Equals
            Return x.Id = y.Id
        End Function
     
        Public Function GetHashCode1(obj As Season) As Integer Implements IEqualityComparer(Of Season).GetHashCode
            Return obj.Id
        End Function
    End Class
    Par contre, je bloque toujours sur la requête linq... J'en suis là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            Dim dto As List(Of PROMO_DTO.PromoDetailOwn) = detailsOwn
            Dim data = (From d1 As PROMO_DTO.PromoDetailOwn In dto
                        From d2 As PROMO_DTO.PromoDetailOwn In dto
                        Where d1.Brand.Id = d2.Brand.Id And d1.Department.Id = d2.Department.Id And d1.Id <> d2.Id And d1.Seasons.Intersect(d2.Seasons).Count > 0
                        Select d1)
    Si je ne mets pas d1.Id <> d2.Id dans le where, ça marche il trouve bien des résultats mais en fait, il trouve tout vu que chaque instance à la même liste qu'elle-même... Mais en l'état, cette query ne renvoie aucun résultat... Moi pas comprendre...

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

Discussions similaires

  1. [XL-2007] Comment créer une dépendance entre deux listes avec des données issus d'un tableau?
    Par efesdark dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 04/07/2011, 17h22
  2. Réponses: 20
    Dernier message: 27/07/2010, 16h52
  3. Concatenation des éléments de deux listes
    Par bellak dans le forum Linq
    Réponses: 7
    Dernier message: 02/06/2010, 15h32
  4. Permutez des éléments entre deux zones deux listes
    Par dricks dans le forum VBA Access
    Réponses: 2
    Dernier message: 14/09/2007, 10h56
  5. Réponses: 2
    Dernier message: 27/10/2006, 19h22

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