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

Framework .NET Discussion :

Création d'un hashCode avec deux paramètres


Sujet :

Framework .NET

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    849
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2004
    Messages : 849
    Points : 295
    Points
    295
    Par défaut Création d'un hashCode avec deux paramètres
    Bonjour,

    J'ai une class avec deux propriétés "clés" A(long?) et B (string) et d'autres propriétés
    Pour faire des comparaisons avec des list j'utilise IEqualityComparer

    La comparaison se fait sur A et B. Si au moins un des éléments A ou B est identique alors l'objet est identique.

    Or mon problème vient du HashCode. Il faut lorsque A et B même différent retourne le même hash, pour être comparer. Avez-vous une idée ?

    Code C# : 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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace ConsoleApplication3
    {
        class Program
        {
            static void Main(string[] args)
            {
                var objA = new Toto { A = 45, B = "X" };
                var objB = new Toto { A = 4, B = "D" };
                var objC = new Toto { A = 5, B = "X" };
                var objD = new Toto { A = 45, B = "A" };
     
                WriteToto(objA);
                WriteToto(objB);
                WriteToto(objC);
                WriteToto(objD);
     
                //Ne doit retourner que des TRUE
                Console.WriteLine(objA.GetHashCode() == objB.GetHashCode());
                Console.WriteLine(objA.GetHashCode() != objC.GetHashCode());
                Console.WriteLine(objA.GetHashCode() == objC.GetHashCode());
                Console.WriteLine(objA.GetHashCode() == objD.GetHashCode());
     
                var listA = new List<Toto>();
                var listB = new List<Toto>();
     
                listA.Add(objA);
                listA.Add(objB);
                listA.Add(objC);
                listA.Add(objD);
     
                listB.Add(objA);
     
                var list = listA.Intersect(listB, new TotoComparer()).ToList();
                //Normalement je devrai récuperer A, C, D
                Console.WriteLine(list.Count == 3);
                Console.WriteLine(list.Contains(objA));
                Console.WriteLine(list.Contains(objC));
                Console.WriteLine(list.Contains(objD));
     
                list = listA.Except(listB, new TotoComparer()).ToList();
                //Normalement je devrai récuperer B
                Console.WriteLine(list.Count == 1);
                Console.WriteLine(list.Contains(objB));
                Console.ReadLine();
            }
     
            public static void WriteToto(Toto t)
            {
                Console.WriteLine(t.ToString() + " " + t.GetHashCode());
            }
        }
     
        public class Toto
        {
            public long? A { get; set; }
            public string B { get; set; }
     
            public string C { get; set; }
     
            public override string ToString()
            {
                return base.ToString();
            }
     
            public override int GetHashCode()
            {
                //hash code à faire
                return A.GetHashCode();
            }
        }
     
        public class TotoComparer : IEqualityComparer<Toto>
        {
            public bool Equals(Toto x, Toto y)
            {
                return
                    (
                        (x.A.HasValue) && (x.A == y.A)
                     ||
                        (x.B == y.B)
                        )
     
     
                    ;
            }
     
            public int GetHashCode(Toto obj)
            {
                return obj.GetHashCode();
            }
        }
    }


    Merci beaucoup de votre aide

  2. #2
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    A priori la seule solution est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public override int GetHashCode()
    {
        //hash code à faire
        return 0;
    }
    Concernant le résultat final seule compte l'égalité.
    Le hash code est une optimisation, notamment dans le cadre des hash maps.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    849
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2004
    Messages : 849
    Points : 295
    Points
    295
    Par défaut
    Le problème c'est que dans mon vrai cas, j'ai des deux list avec 10000 élements, et la comparaison met beaucoup de temps. D'où le hash

  4. #4
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Si tu fais ce type d'opérations ensemblistes essaye en stockant tes objets dans des Dictionary et utilise un hash "normal" du coup :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public override int GetHashCode()
    {
        //hash code à faire
        return (A ?? 0).GetHashCode() ^ (B ?? "").GetHashCode() ^ (C ?? "").GetHashCode();
    }
    Il y a des fonctions de hash avec de meilleures caractéristiques statistiques mais teste déjà avec ça.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    849
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2004
    Messages : 849
    Points : 295
    Points
    295
    Par défaut
    Le hash de l'objet C, n'est pas bon.

  6. #6
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    C'est à dire ?

    Si pour ta comparaison spécifique tu n'utilises pas C alors en effet tu peux changer dans l'IEqualityComparer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public int GetHashCode(Toto obj)
    {
        return (obj.A ?? "").GetHashCode() ^ (obj.B ?? "").GetHashCode();
    }
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    849
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2004
    Messages : 849
    Points : 295
    Points
    295
    Par défaut
    pardon je n'étais pas clair. J'avais fait la modification je parle de ce morceau de code avec objC et non de la propriété C

    Les objets objA,objC, et objD doivent avoir le même hashCode

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var objA = new Toto { A = 45, B = "X" };
                var objB = new Toto { A = 4, B = "D" };
                var objC = new Toto { A = 5, B = "X" };
                var objD = new Toto { A = 45, B = "A" };
     
                WriteToto(objA);
                WriteToto(objB);
                WriteToto(objC);
                WriteToto(objD);
     
     
     public static void WriteToto(Toto t)
            {
                Console.WriteLine(t.ToString() + " " + t.GetHashCode());
            }

  8. #8
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Dans ce cas IMHO la seule "transformation" possible est l'identité comme je l'ai fait au début en renvoyant tout le temps 0, mais 42 aurait aussi bien fait l'affaire.

    Donc la ventilation de tes données dans une hash map ne sera pas possible, donc niveau performance j'ai bien peur que tu ne puisses pas faire mieux que O(n²).
    L'intérêt d'une hash map (IDictionary) était justement de faire l'intersection en O(n) (théoriquement du moins).
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    849
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2004
    Messages : 849
    Points : 295
    Points
    295
    Par défaut
    Au lieu d'utiliser une list je dois utiliser un IDictionnary ?

  10. #10
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Non malheureusement dans ce cas ça sera inutile car il n'y aura qu'un seul bucket puisque tous tes objets auront le même hash code.

    Donc à mon avis il va falloir vivre avec ces performances ou monter un système un peu plus complexe tenant compte des particularités de tes objets.

    Peut être que sur le forum algos certains auront d'autres pistes, mais concernant .Net je pense que tout est dit. :/
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

Discussions similaires

  1. Réponses: 8
    Dernier message: 10/12/2007, 16h27
  2. [Visual Web] Query avec deux paramètres
    Par eponette dans le forum NetBeans
    Réponses: 1
    Dernier message: 19/03/2007, 13h44
  3. [MySQL] La pagination avec deux paramètres
    Par arti2004 dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 05/10/2006, 14h25
  4. Réponses: 3
    Dernier message: 28/04/2006, 10h17
  5. Procédure stockée avec deux paramètres ADO/ORACLE
    Par zanifu dans le forum Bases de données
    Réponses: 7
    Dernier message: 01/03/2006, 09h13

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