Bonjour :)
Quelqu'un connaîtrait-il un algo C# pour détecter des doublons dans une List<string> ?
Ou y-t-il déjà qqch de prévu dans le framework ?
Merci bien :)
Version imprimable
Bonjour :)
Quelqu'un connaîtrait-il un algo C# pour détecter des doublons dans une List<string> ?
Ou y-t-il déjà qqch de prévu dans le framework ?
Merci bien :)
Utilise la méthode Contains :)
List<String> list = new List<String>();
foreach(string s in list)
{
if (list.Contains(s))
{
// Ta liste contient s
}
}
Salut,
Morpheus, je crois que ton algorithme n'est pas bon, la liste contient forcement s.Citation:
Envoyé par Morpheus
Ou surement tu voulais faire ca :
Code:
1
2
3
4
5
6 List<String> ListAvecDuplication = new List<String>(); List<String> ListSansDuplication = new List<String>(); foreach (string s in ListAvecDuplication ) if (!ListSansDuplication.Contains(s)) ListSansDuplication .Add(s);
Ah oui, c'est pas bête: je me disais bien qu'il manquait des lignes d ecode :lol:
Enfin, l'important ici, c'est tout de même la méthode Contains ;)
:P
T'inquiete on est là pour terminer tes lignes de codes manquantes, tu n'a qu'à proposer l'idée :lol:
Ah, pas mal ton algo :)
Je me disais bien qu'il fallait pas prendre chaque élément et les comparer à tous les autres :lol:
Par contre, il manque la fin de l'algo.
Je suppose qu'il suffit de comparer le nombre d'élements de chaque liste, et si ceux-ci sont différents, c'est qu'il y avait un doublon dans la liste.
Merci bcp à vous en tout cas :)
Ah la non je ne savais qu'il fallait juste savoir s'il y avait des doublons
dans ce cas :
Pas la peine de terminer la boucle dés que tu trouve le premier doublon tu sors (break;)Code:
1
2
3
4
5
6
7
8
9
10
11
12 List<String> ListAvecDuplication = new List<String>(); List<String> ListSansDuplication = new List<String>(); bool IlExisteDesDoublons=false; foreach (string s in ListAvecDuplication ) if (!ListSansDuplication.Contains(s)) ListSansDuplication .Add(s); else { IlExisteDesDoublons=true; break; }
Ah oui, pas bête...
Je commanderai un cerveau pour Noël :mouarf:
Mici bien :)
Bonjour,
Je reviens sur ce topic.
La méthode proposée par mehdi_tn fonctionne parfaitement si votre liste est composé de string.
De mon côté, j'ai une liste contenant des objets personne.
Like this :
J'ai besoin de supprimer les doublons de ma liste sur deux attributs de mon objet personne (ex : le nom et le prénom)Code:
1
2 List<Personne> ListPersonne = new List<Personne>();
En gros, si une personne a le meme nom & le meme prénom qu'un autre alors je le supprime.
Visiblement je ne peux pas utiliser la méthode Contains, exact ?
Thx
peu être qu'en implémentant l'interface IComparable ca résoudrait le problème?
Je t'avoue y avoir penser mais je ne maitrise pas vraiment le sujet :oops:
Si tu as un exemple de code ?
Salut dacamp, tu es en quelle version du framework ?
je suis en 2.0 sinon je ne pourrais pas utiliser les Collections.Generic tel que les listes fortement typées ;)
La méthode contains et l'interface IComparabale existent depuis le framework 1.0, avant que les listes génériques voient le jour dans Dot Net, d'où ma question.
D'abord cherche dans le forum Dot Net IComparable ; tu trouveras plein d'exemples.
Sinon y'a l'exemple de msdn CompareTo
à lequel tu dois surcharger la méthode equals , voici un exemple Override methods on comparable types
Je sais que cela existe mais je ne le maitrisais déjà pas tres bien en 1.0.
J'utilise la méthode Compare pour trier ma liste typée au préalable afin d'optimiser (je l'espère) le futur dédoublonnage 8O
Maintenant, je ne comprends pas pourquoi la méthode Contains me sort que deux objets personnes sont différents alors que tous les attributs de mon objet sont identiques ... je seche complet. Enfin, je vais creuser un peu plus le problème et je reviendrai pour donner le résultat de mes recherches
Démonstration par l'exemple.
Distri est une classe contenant une liste d'attributs + getter et setter
Le résultat de ce morceau de code m'indique qu'il passe dans le résultat du if. Il m'ajoute donc un 2ème élément à la liste v_listeSansDoublon.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 //test List<Distri> v_listeSansDoublon = new List<Distri>(); List<Distri> v_listeAvecDoublon = new List<Distri>(); Distri toto1 = new Distri(); toto1.EAN17 = "2121"; v_listeAvecDoublon.Add(toto1); Distri toto2 = new Distri(); toto2.EAN17 = "2121"; v_listeSansDoublon.Add(toto2); foreach (Distri v_distri in v_listeAvecDoublon) if (!v_listeSansDoublon.Contains(v_distri)) v_listeSansDoublon.Add(v_distri);
Parce que la comparaison se fait par defaut sur les references, tu dois modifier ce comportement.Citation:
Envoyé par dacamp
Pour ton probleme, montre comment tu as implementer Distri.
Merci de ton aide, c'est bien cool :D
Voici ma classe Distri
Code:
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183 using System; using System.Collections.Generic; using System.Text; namespace InfertaceDistrirama { class Distri { public Distri() { } private string m_codeOPE; private string m_numOPE; private string m_statutOP; private string m_blanc1; private string m_niveauOPE; private string m_codeClient; private string m_blanc2; private string m_EAN13; private string m_EAN17; private string m_dateDebAppro; private string m_dateFinAppro; private string m_dateDebComm; private string m_dateFinComm; private string m_semaine; private string m_annee; private string m_codeOS; private string m_codePR; private string m_prixForce; private string m_prixTarif; private string m_remise; private string m_mttRemise; private string m_tauxCGV; private string m_SRPTTC; #region Getter & Setter public string Blanc1 { get { return m_blanc1; } set { m_blanc1 = value; } } public string Blanc2 { get { return m_blanc2; } set { m_blanc2 = value; } } public string NiveauOPE { get { return m_niveauOPE; } set { m_niveauOPE = value; } } public string CodeClient { get { return m_codeClient; } set { m_codeClient = value; } } public string EAN13 { get { return m_EAN13; } set { m_EAN13 = value; } } public string CodeOPE { get { return m_codeOPE; } set { m_codeOPE = value; } } public string NumOPE { get { return m_numOPE; } set { m_numOPE = value; } } public string StatutOP { get { return m_statutOP; } set { m_statutOP = value; } } public string SRPTTC { get { return m_SRPTTC; } set { m_SRPTTC = value; } } public string TauxCGV { get { return m_tauxCGV; } set { m_tauxCGV = value; } } public string MttRemise { get { return m_mttRemise; } set { m_mttRemise = value; } } public string Remise { get { return m_remise; } set { m_remise = value; } } public string PrixTarif { get { return m_prixTarif; } set { m_prixTarif = value; } } public string PrixForce { get { return m_prixForce; } set { m_prixForce = value; } } public string CodePR { get { return m_codePR; } set { m_codePR = value; } } public string CodeOS { get { return m_codeOS; } set { m_codeOS = value; } } public string Semaine { get { return m_semaine; } set { m_semaine = value; } } public string Annee { get { return m_annee; } set { m_annee = value; } } public string DateFinComm { get { return m_dateFinComm; } set { m_dateFinComm = value; } } public string DateDebComm { get { return m_dateDebComm; } set { m_dateDebComm = value; } } public string DateDebAppro { get { return m_dateDebAppro; } set { m_dateDebAppro = value; } } public string DateFinAppro { get { return m_dateFinAppro; } set { m_dateFinAppro = value; } } public string EAN17 { get { return m_EAN17; } set { m_EAN17 = value; } } #endregion Getter & Setter } }
Je tente une idée : on doit modifier
la classe EqualityComparer ??
Oui t'as raison, je suis parti sur une mauvaise piste : je pensais à la fonction de tri de la list.
en fait ta classe doit implementer l'interface IEquatable
Par exemple :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 public class Personne : IEquatable<Personne> { string _nom; string _prenom; public Personne(string n, string p) { _nom = n; _prenom = p; } public bool Equals(Personne other) { return _nom == other._nom && _prenom == other._prenom; } }
Chapeau bas monsieur, Cela fonctionne nikel !
J'abuse mais à titre d'information, je me demandais pourquoi tu faisais une comparaison entre 2 string en utilisant == plutot que .Equals ?
Merci beaucoup mehdi_tn !
Medhi, pour tout te dire, ma liste contient environ 115 000 objets.
J'ai commencé par faire un tri au préalable mais je commence à me demander si cela est nécessaire pour lancer ma comparaison d'objet.
Le traitement est vraiment très long ...
Encore une question, je sais je commence à être pénible ;)Citation:
Envoyé par mehdi_tn
La comparaison se fait sur les références ? cela veut dire quoi exactement ?
ça signifie qu'il regarde l'adresse ou est stockée la valeur et non la valeur elle même si je ne me trompe pas.
Je te fais une analogie facile a capter :
Jean dupont et jean dupont sont deux jumeaux ils ont la même adress ele même age, les même parent etc... ils sont identique et pourtant ce sont 2 individu different donc
Pour que tes deux individu jean dupont soit considéré comme identique tu doit créer une "règle" qui dit par exemple :Code:Jean dupont <> Jean dupont
Voilà :)Citation:
Si l'individu A a le même age et la même adresse que l'individu B alors il sont considéré comme étant identique
Merci ekinox17.
pourrais tu aussi me répondre aussi simplement pour mes autres questions ? :oops:
c'est pareil juste une question de synataxe, le double egal est peut etre même plus rapide a executé enfin je ne sais pas je n'ai pas tester, mais a l'origine le double egal est un signe comparatif du langage C tantdis que la fonction equal est une fonction implementé par la framework.Citation:
je me demandais pourquoi tu faisais une comparaison entre 2 string en utilisant == plutot que .Equals ?
Aïe :cry: ça fait beaucoup, tu te demande si cela est necessaire de trier pour les comparé ? et bien non tu devrais relire les très bon conseils de mehdi_tn qui a dit qu'il était parti sur une mauvaise voie.Citation:
Medhi, pour tout te dire, ma liste contient environ 115 000 objets.
J'ai commencé par faire un tri au préalable mais je commence à me demander si cela est nécessaire pour lancer ma comparaison d'objet.
Le traitement est vraiment très long ...
Il t'as réorienté en te disant que cela n'etais pas nécessaire mais que tu devais plutot implementer IEquatable et non pas IComparable.
Merci ekinox17 pour l'aide :). Je vais essayer d'expliquer pareil.Citation:
Envoyé par ekinox17
supposons que tu as deux string jumeaux Jean Batiste et Jean dupont. Leur pere qui est le framework dot net est aveugle, il doit utiliser la méthode equals qui va comparer l'age l'adresse et tout le reste pour reconnaitre ses jumeaux. La mere du framework est aveugle aussi comme par hasard, mais elle n'aime pas utiliser la fonction equals pour une raison que je ne connais pas. Mais elle connais un opérateur == qui pourrait faire l'affaire. Alors elle demande à son mari Mr framework dot net de surcharger cet opérateur pour qu'il soit utilisé comme le equal. Voila maintenant tu peux comparer les string soit avec equals ou ==. Mais à la base == est utiliser pour comparer les references comme ekinox17 te la bien expliqué. Voir Override operator equals on overloading add and subtract , pour plus d'explication.Citation:
Envoyé par dacamp
Maintenant pour l'histoire du tri. Si tu veux que ta liste soit tout le temps triée dans ce cas utilise plutôt la collection SortedList ou SortedDictionary en ignorant les valeurs (c'est des structures Clé/Valeur). Tu trouveras dans ces liens la difference entre ces deux Collections. A priori c'est la SortedDictionary qu'il te faut.
L'autre moyen c'est d'utiliser la fonction Sort de ta list, là c'est normal que le traitement soit long.
Dans tous les cas il faut implémenter IComaparable dans ta classe ou passer un objet Icomparer, au moins notre discussion aura servi ;)
Encore merci Mehdi.
Pour continuer sur ma lancée et comme tu connais le sujet, j'ai une autre question. Comme je commence à mieux comprendre les interfaces, je me lance dans un dev qu'auparavant j'aurais contourné ...
Je désire utiliser un foreach afin de parcourir chaque élément de mon objet distri. (mes attributs sont tous des strings)
Donc je fais :
Malheureusement cela ne fonctionne pas et pour cause il n'existe pas de méthode GetEnumerator dans ma classe Distri.Code:
1
2
3
4 foreach (String v_element in distri) { }
tu vois, je progresse 8-)
Par contre,ensuite je sechè :oops:
Tu peux m'expliquer car comme ma classe herite deja de :
Comment je peux faire ?Code:
1
2class Distri : IEquatable<Distri>
Je crois qu'il faut implémenter IEnumerable
Bon j'ai la réponse à ma dernière question même si je ne sais pas si cela est la meilleure méthode.
Dans ma classe Distri j'ajoute la méthode GetEnumerator comme suit :
ensuite je peux utiliser le foreach sur mon objet v_distri :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 public IEnumerator<string> GetEnumerator() { string[] v_listElements = new string[23]; v_listElements[0] = m_codeOPE; v_listElements[1] = m_numOPE; v_listElements[2] = m_statutOP; foreach (string v_element in v_listElements) { yield return v_element; } }
Maintenant je repete que cela n'est peut etre pas la bonne méthode mais elle fonctionne. Je suis à l'écoute de toute suggestion sur le sujet. 8OCode:
1
2
3
4
5 foreach (string v_element in v_distri) { (...) }
Just ajouter que c'est mieux d'utiliser StringCollection (C# 2.0)
Eviter :
Mieux:Code:List<string> lst = new List<string>();
:)Code:StringCollection lst = new StringCollection();
ok merci pour cette précision.
j'ai une question pratique ... je ne trouve plus le tag résolu, normal ?
tout a fait normal, vu que tu n'es pas l'auteur du premier post ;)
LOL ... pas con en effet :)
A partir du .NET 3.5, on peut faire plus simple pour savoir si la liste a des doublons :
Code:
1
2
3
4
5 if (maList.Count == maList.Distinct().Count()) { // Pas de doublon } else { // Ya des ou un doublon }
Code:L.RemoveAll(Function(s As String) L.FindAll(Function(ss As String) ss = s).Count > 1)