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

C# Discussion :

[C#] Comparer les valeurs de deux listes d'objets


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut [C#] Comparer les valeurs de deux listes d'objets
    Bonjour,

    Dans mon application, j'implémente deux listes d'objets à 30s d'écart :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    List<Object> list1 = MethodQuiRempliLaList();
    Thread.Sleep(30000);
    List<Object> list2 = MethodQuiRempliLaList();
    Les données contenues dans les objets sont de ce type :

    [0]----[1]
    User1 val1
    User2 val2
    User3 val3
    ... ...

    J'aimerais pouvoir comparer les changements de valeurs des lists en fonction de l'index [0] c'est à dire que si la list1 contient :


    [0]----[1]
    User1 val1
    User2 val2
    User3 val3
    ... ...


    Et que la list2 contient :


    [0]----[1]
    User1 val1
    User2 val40
    User3 val58
    ... ...


    Et que si je compare les deux lists, j'obtienne une troisième lists contenant :


    [0]----[1]
    User2 val40
    User3 val58


    Je pense qu'il y'a des fonctions faisant ça automatiquement mais je n'arrive pas à les adapter à mon problème .

  2. #2
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Tu peux utiliser la methode d'extension Except. Dans ton cas ca donnerait ceci pour obtenir le résultat que tu souhaites :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    var list3 = list2.Except(list1);
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  3. #3
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2006
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 97
    Points : 65
    Points
    65
    Par défaut
    Bonjour,
    La fonction Except sur un IEnumerable<T> est faite pour cela.

    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
    class Program
        {
            static void Main(string[] args)
            {
                var list1 = new List<Toto>()
                {
                    new Toto(){Name="Toto1",Val=1},
                    new Toto(){Name="Toto2",Val=2},
                    new Toto(){Name="Toto3",Val=3},
                    new Toto(){Name="Toto4",Val=4},
                };
     
     
                var list2 = new List<Toto>()
                {
                    new Toto(){Name="Toto1",Val=1},
                    new Toto(){Name="Toto2",Val=20},
                    new Toto(){Name="Toto3",Val=30},
                    new Toto(){Name="Toto4",Val=4},
                };
     
     
                var diff = list2.Except(list1, new TotoEqualityComparer());
                foreach (var totoDiff in diff)
                {
                    Console.WriteLine("{0} -> {1}", totoDiff.Name, totoDiff.Val);
                }
     
     
            }
     
            private class TotoEqualityComparer : IEqualityComparer<Toto>
            {
     
                public bool Equals(Toto x, Toto y)
                {
                    return x.Name.Equals(y.Name) && x.Val == y.Val;
                }
     
                public int GetHashCode(Toto obj)
                {
                    return obj.Name.GetHashCode(); // libre choix du GetHashCode
                }
            }
     
            private class Toto
            {
                public String Name { get; set; }
                public int Val { get; set; }
            }
        }

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    Ta solution me parait séduisante Moumoune, cependant je ne connais pas le nom des champs de ma list, c'est pour ça que j'utilise une List d'object.

    Est-ce toujours compatible ?

  5. #5
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Pas la peine de se compliquer la vie, la solution tient en une seule ligne, même sur une List<object>. L'utilisation d'un EqualityComparer n'est pas nécessaire dans ce cas.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    Pourtant quand j'écris ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
                    var list3 = listCur.Except(listPrec);
                    foreach (var totoDiff in list3)
                    {
                        eL.EventLoginWritter("Comparaison : " + ((object[])(totoDiff))[0] + " " + ((object[])(totoDiff))[2]);
     
                    }
    la list3 contient l'intégralité de la liste listCur alors qu'elle ne devrait contenir que les objets ayant changés je ne comprends pas

  7. #7
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Que contient ta liste précisément ? Des Array, des types anonymes ou autre ?
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    C'est une liste de type Object que je déclare de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    List<Object> list1;
    Chaque Object possède 3 champs tous de type string.

  9. #9
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Bizarre, voici un exemple similaire. Je charge une première liste, avec i allant de 0 à 100 :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var list1 = new List<object>();
    for (var i = 0; i <= 100; i++)
    {
        list1.Add(new { A = "User" + i, B = "val" + i });
    }
    Ensuite je charge une seconde liste avec i allant de 0 à 500 (donc avec Except je récupère bien les 400 éléments supplémentaires qui ne sont pas dans list1). Pour corser un peu, lorsque i est un multiple de 2, j'ajoute à i un nombre aléatoire. Au final Except me retournera donc tous les éléments pairs puisque leur valeur ne correspond pas à celle de list1 :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var list2 = new List<object>();
    for (var i = 0; i <= 500; i++)
    {
        var number = i;
        if (i % 2 == 0)
        {
            number += _r.Next();
        }
     
        list2.Add(new { A = "User" + i, B = "val" + number });
    }
    Au final, j'utilise Except :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    var list3 = list2.Except(list1).ToList();
    Et j'obtiens bien le résultat attendu : les 400 éléments supplémentaires de list2 qui ne sont pas dans list1, et tous les éléments pairs de list2 allant de 0 à 100 puisque j'ai changé leur valeur donc il n'ont pas d'équivalent dans list1.

    Est-ce que cet exemple reproduit ton scénario ?

    Dans ton cas est-ce que tu ne devrais pas appeler Except sur la listPrec et non sur la listCur ?
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    var list3 = listPrec.Except(listCur);
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    Ton code fonctionne bien.

    Je ne comprend pas pourquoi mes lists ne fonctionnent pas . Voici comment mes listes sont aliementées :


    1 : Lecture du DataSet et insertion dans une Liste d'objects les différentes valeurs
    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
     
    List<Object> stockResult
                    while (data.Read())
                    {
                        int taille = data.VisibleFieldCount;
                        Object[] mem = new Object[taille];
                        for (int i = 0; i <= taille-1; i++)
                        {
                            if (data[i] != DBNull.Value) mem[i] = data.GetString(i).ToString();
                        }
                        stockResult.Add(mem);
     
     
                    }
                    data.Close();
    2 : Je refait 5 minutes plus tard la procédure 1. Les données ont changé.

    3: Je fais une comparaison des deux listes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
                    var list3 = listCur.Except(listPrec);
                    foreach (var totoDiff in list3)
                    {
                        eL.EventLoginWritter("Comparaison : " + ((object[])(totoDiff))[0] + " " + ((object[])(totoDiff))[2]);
                        //Console.WriteLine("{0} -> {1}", totoDiff.Name, totoDiff.Val);
                    }
    Et list3 contient toutes les données de listCur alors qu'en réel, seul un object a changé

  11. #11
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Ok je vois. J'étais parti sur l'hypothèse que tes objets étaient des types anonymes, mais en fait ce sont des tableaux d'object. Tu as 2 solutions :
    - Soit utiliser la solution préconisée par moumoune65 en utilisant un EqualityComparer.
    - Soit utiliser des types anonymes au lieu de tableaux d'objets et ainsi éviter d'utiliser un EqualityComparer.

    Pour implémenter un EqualityComparer sur un tableau, voici un exemple:

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class MyEqualityComparer : IEqualityComparer<object[]>
    {
     
    	public bool Equals(object[] x, object[] y)
    	{
    		return x[0].Equals(y[0]);
    	}
     
    	public int GetHashCode(object[] obj)
    	{
    		return obj.GetHashCode(); // libre choix du GetHashCode
    	}
    }

    Et pour l'utilisation :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    var list3 = listCur.Except(listPrec, new MyEqualityComparer());
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    Bonjour,

    J'espère que vous avez passé un bon Week-End,
    J'ai essayé d'implémenter votre EqualityComparer mais à la ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    var list3 = listCur.Except(listPrec, new MyEqualityComparer());
    j'obtiens l'erreur : "impossible de convertir de 'System.Collections.Generic.List<object>' en 'System.Linq.ParallelQuery<object[]>'"

  13. #13
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Tu as indiqué que tu utilisais des List<Object> donc le code donné est écrit en fonction de cela. Il n'a jamais été question de ParallelQuery.

    A priori tu as du rajouter un traitement sur listPrec
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

Discussions similaires

  1. Réponses: 2
    Dernier message: 21/03/2013, 18h38
  2. Comparer les valeurs de deux colonnes d'une feuille excel
    Par charrynsasi dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 03/12/2012, 14h40
  3. [SQL-Server] recuperer les valeurs de deux listes sur la meme page
    Par manel ingenieur dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 23/12/2010, 11h48
  4. Comparer les valeurs de deux tableaux
    Par mailbox dans le forum Débuter
    Réponses: 12
    Dernier message: 28/11/2010, 19h14
  5. [DeskI XiR2] Comparer les valeurs de deux colonnes
    Par EmmanuelleC dans le forum Débuter
    Réponses: 2
    Dernier message: 27/02/2009, 08h45

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