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 :

Unique List<> Item. Eviter les valeurs en double dans List<> par ajout d'une méthode AddUnique()


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 247
    Points : 106
    Points
    106
    Par défaut Unique List<> Item. Eviter les valeurs en double dans List<> par ajout d'une méthode AddUnique()
    Bonjour,

    J'ai besoin d'une collection sérialisable avec aucune valeurs en double. J'utilise présentement un test avant d'insérer un objet dans une liste List<>.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (!NASDAQStocksFollowUpList.Exists(x => x.Symbol == "AAPL"))
    NASDAQStocksFollowUpList.Add(new NASDAQFollowUpStocks { Symbol = "AAPL", Name = "Microsoft", LastPrice = 0, BuyingDate = DateTime.Now, Price = 0 });
    mais j'aimerais mieux faire ceci avec le test dans la méthode AddUnique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     UniqueNASDAQStocksFollowUpList.AddUnique(new NASDAQFollowUpStocks { Symbol = "AAPL", Name = "Apple Inc.", LastPrice = 0, BuyingDate = DateTime.Now, Price = 0 });
    J'ai donc créé un autre type de List<> avec ajout de AddUnique() mais j'ai un problème voir dans le code ci-dessous.

    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
        class UniqueList<NASDAQFollowUpStocks> : List<NASDAQFollowUpStocks>
        {
            public bool AddUnique(NASDAQFollowUpStocks item)
            {
               // 'NASDAQFollowUpStocks' does not contain a definition for 'Symbol' and no accessible extension method 'Symbol' accepting a first argument of type 'NASDAQFollowUpStocks' could be found(are you missing a using directive or an assembly reference ?)
                if (this.Exists(x => x.Symbol == item.symbol))  // Problème ici j'ai essayé un cast avant je ne trouve pas. Qu'est-ce qui ne va pas ?
                {
                    return false;
                }
                else
                {
                    this.Add(item);
                    return true;
                }
            }
        }
    Voici la classe utilisé qui doit être sérialisable

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    namespace Add_AddUnique_Method
    {
        // Attention je dois sauver et récupèrer la liste ça fonctionne très bien et ce n'est pas le problème mais  [Serializable] ça doit rester là
        [Serializable]
        class NASDAQFollowUpStocks
        {
            public string Symbol { get; set; }
            public string Name { get; set; }
            public double Price { get; set; }
            public DateTime BuyingDate { get; set; }
            public double LastPrice { get; set; }
        }
    }
    J'ai horreur de l'aide en ligne de Microsoft c'est impossible de si retrouver la-dedans. Je vais me commander un livre en C# finalement.

    J'ai écris un petit programme juste pour tester vous n'avez donc rien à taper.

    Bonne fin de journée à tous. Bye!
    Fichiers attachés Fichiers attachés

  2. #2
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour

    Pourquoi n'utilise -tu pas System. KeyedCollection<TKey, TItem>(espace de noms System.Collections.ObjectModel) c'est une mixture de List<T> et de IDictionary<(Of <(TKey, TValue>)>).
    Voici un extrait de la Rubrique MSDN Library Help Fr inttitulé "KeyedCollection<(Of <(TKey, TItem>)>), classe "
    une collection basée sur l'interface générique IDictionary<(Of <(TKey, TValue>)>). À l'instar des collections basées sur l'interface générique IList<(Of <(T>)>), KeyedCollection<(Of <(TKey, TItem>)>) est une liste indexée d'éléments. À l'instar des collections basées sur l'interface générique IDictionary<(Of <(TKey, TValue>)>), KeyedCollection<(Of <(TKey, TItem>)>) a une clé associée à chaque élément....etc

    De plus dans cette rubrique ,le 2eme exemple de code fournit une implementation de liste avec comportement personnalisée ...
    bon code...

  3. #3
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par PiPo123 Voir le message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        class UniqueList<NASDAQFollowUpStocks> : List<NASDAQFollowUpStocks>
               // 'NASDAQFollowUpStocks' does not contain a definition for 'Symbol' and no accessible extension method 'Symbol' accepting a first argument of type 'NASDAQFollowUpStocks' could be found(are you missing a using directive or an assembly reference ?)
                if (this.Exists(x => x.Symbol == item.symbol))  // Problème ici j'ai essayé un cast avant je ne trouve pas. Qu'est-ce qui ne va pas ?
    Attention, C# est sensible à la casse. "symbol" et "Symbol" ne sont pas équivalent !
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 247
    Points : 106
    Points
    106
    Par défaut
    C'est une erreur lorsque que j'ai entré le code sur le site. J'ai bien ceci dans le code.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ...
    if (this.Exists(x => x.Symbol == item.Symbol))  // Problème ici j'ai essayé un cast avant je ne trouve pas. Qu'est-ce qui ne va pas ?
    ...

    Il y a beaucoup de discussion sur ce sujet.

  5. #5
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Roh, la belle blagounette. Le problème vient que dans le code, au niveau de la classe UniqueList, NASDAQFollowUpStock ne représente pas la classe du même nom, mais est considéré comme un paramètre générique (déclaration d'une classe générique). Aussi, impossible pour le compilateur de savoir quelles sont les propriétés disponibles.

    Le code que tu as écrit est donc l'équivalent de celui-ci :
    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
    class UniqueList<T> : List<T>
        {
            public bool AddUnique(T item)
            {
     
     
                // Voilà le problème
                // 'NASDAQFollowUpStocks' does not contain a definition for 'Symbol' and no accessible extension method 'Symbol' accepting a first argument of type 'NASDAQFollowUpStocks' could be found(are you missing a using directive or an assembly reference ?)
                if (this.Exists(x => x.Symbol == item.Symbol))  // Problème ici j'ai essayé un cast avant je ne trouve pas. Qu'est-ce qui ne va pas ?
                {
                    return false;
                }
                else
                {
                    this.Add(item);
                    return true;
                }
            }
        }
    Deux solutions existent.

    La première, est de rajouter une contrainte pour préciser que le paramètre générique doit dériver de NASQDAQFollowUpStock
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class UniqueList<T> : List<T> where T:NASDAQFollowUpStocks
    La seconde, déclarer la classe sans généricité
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class UniqueList : List<NASDAQFollowUpStock>
    Ce qui ne me semble pas complètement déconnant vu la situation, dans le sens où le AddUnique à besoin de connaître la structure de l'objet ajouté. Mais du coup, je renommerai la classe en quelque chose de plus parlant, style NASDAQFollowUpStockList
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  6. #6
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 896
    Points : 1 912
    Points
    1 912
    Par défaut
    Concernant l'erreur de compilation François a déjà répondu, je ne reviendrai pas dessus. Sinon je voyais deux autres options pour résoudre ton problème de doublon. La première, si l'ordre des éléments n'est pas important, est d'utiliser tout simplement un HashSet<T>, qui permet d'avoir un jeu de valeurs uniques, un peu comme le suggère MABROUKI. Il est même possible de fournir un objet IComparer afin d'avoir une méthode de comparaison spécifique à ton besoin. Une autre consiste à utiliser une méthode d'extension pour implémenter cette méthode de contrôle sans utiliser tout le système de l'héritage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static MyExtensions
    {
      public static bool AddOnce(this List<NASDAQFollowUpStocks> source, NASDAQFollowUpStocks item)
      {
        if(source == null) throw new ArgumentNullException("source");
        if(source.Exist(x => x.Symbol == item.Symbol)) return false;
        return source.Add(item);
      }
    }
    Mais quelle que soit la solution il demeurera un trou dans ta raquette. Il semble que ce soit la propriété Symbol de la classe NASDAQFollowUpStocks qui définisse l'unicité d'un item dans la liste. Or cette propriété est en lecture/écriture. Ce qui signifie que s'il n'est pas possible d'ajouter un item qui aura une valeur déjà présente il sera en revanche possible de modifier ultérieurement la valeur de cette propriété pour une valeur déjà présente dans la liste.

    Il est possible de mettre cette propriété en lecture seule afin de lui attribuer une sémantique de valeur, ou bien de faire de cette classe une structure (mot clé struct). Sinon il faudra avant de sérialiser la liste vérifier l'absence de doublon.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 247
    Points : 106
    Points
    106
    Par défaut
    Les deux solutions de François fonctionnent parfaitement. Bravo !

    J'ai déjà essayé avec un HashSet<> et ça fonctionne aussi mais comme je suis têtu je veux continuer avec une List<>.

    Je vais remettre le petit programme test. J'ai ajouté un peu de code pour sérialiser et désérialiser la collection moi j'ai besoin de garder les données alors peut-être que ça serait utile aux autres aussi.

    J'ai aussi ajouté du code pour sélectionner quelle propriété de la classe doit être unique dans la collection. Disons est-ce le symbole qui doit être unique ou le nom du Stocks. Vous verrez on a le choix maintenant.

    Bon maintenant c'est dodo.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 247
    Points : 106
    Points
    106
    Par défaut
    Bon voilà. J'ai ajouté le petit programme test.

    Maintenant on initialise avec ceci car j'ai ajouté une option pour choisir la propriété qui doit être unique dans la collection (je ne sais pas si c'est vraiment pertinent mais bof!) et j'ai laissé le code pour sauvegarder la collection dans un fichier aussi pour ceux que ça pourrait intéresser.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UList = new UniqueStocksList<Stocks>(UniqueStocksList<Stocks>.UniqueKey.Name);
    La classe Stocks
    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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace Add_AddUnique_Method
    {
        [Serializable]
        public class Stocks : IComparable
        {
            public string Symbol { get; set; }
            public string Name { get; set; }
     
            public int CompareTo(object obj)
            {
                Stocks orderToCompare = obj as Stocks;
                if (String.Compare(orderToCompare.Symbol, Symbol) < 0)
                {
                    return 1;
                }
     
                if (String.Compare(orderToCompare.Symbol, Symbol) > 0)
                {
                    return -1;
                }
     
                // The orders are equivalent.
                return 0;
            }
     
            [Serializable]
            public class StocksSymbolComparer : IEqualityComparer<Stocks>
            {
                public bool Equals(Stocks x, Stocks y)
                {
                    return x.Symbol.Equals(y.Symbol, StringComparison.InvariantCultureIgnoreCase);
                }
     
                public int GetHashCode(Stocks obj)
                {
                    return obj.Name.GetHashCode();
                }
            }
     
            [Serializable]
            public class DescendingComparer : IComparer<Stocks>
            {
                public int Compare(Stocks x, Stocks y)
                {
                    return y.CompareTo(x);
                }
            }
     
            public override bool Equals(object obj)
            {
                if (obj == null) return false;
                Stocks objAsPart = obj as Stocks;
                if (objAsPart == null) return false;
                else return Equals(objAsPart);
            }
     
            public bool Equals(Stocks other)
            {
                if (other == null) return false;
                return (this.Symbol.Equals(other.Symbol));
            }
        }
    }
    La collection UniqueStocksList
    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
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     
    namespace Add_AddUnique_Method
    {
        [Serializable]
        class UniqueStocksList<T> : List<T> where T : Stocks
        //class UniqueStocksList : List<Stocks>
        {
            public enum UniqueKey
            {
                Symbol,
                Name
            }
     
            private UniqueKey _UniqueKey;
     
            public UniqueStocksList(UniqueKey UK)
            {
                _UniqueKey = UK;
            }
     
            //public bool AddUnique(Stocks item)  // Fonctione avec  class UniqueStocksList<T> : List<T> where T:Stocks
            public bool AddUnique(T item)  // Fonctione avec  class UniqueStocksList<T> : List<T> where T:Stocks
            {
                switch (_UniqueKey)
                {
                    case UniqueKey.Symbol:
                        if (!this.Exists(x => x.Symbol == item.Symbol))
                        {
                            this.Add(item);
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    //break;
                    case UniqueKey.Name:
                        if (!this.Exists(x => x.Name == item.Name))
                        {
                            this.Add(item);
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    //break;
                    default:
                        return false;
                        //break;
                }
            }
        }
    }
    En passant si quelqu'un peut me recommander une livre sur le language C# pour ceux qui savent déjà programmer sans être un expert ou du moins me dire lesquels éviter.

    Merci. Bye.
    Fichiers attachés Fichiers attachés

Discussions similaires

  1. Réponses: 4
    Dernier message: 28/03/2011, 12h02
  2. Réponses: 2
    Dernier message: 14/07/2009, 08h45
  3. Réponses: 2
    Dernier message: 15/10/2007, 13h28
  4. Eviter les sauts de page dans un tableau
    Par jaymzwise dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 31/07/2007, 17h11
  5. [MySQL] Eviter les doublons à l'insertion dans une base
    Par leloup84 dans le forum PHP & Base de données
    Réponses: 23
    Dernier message: 26/01/2006, 15h26

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