PDA

View Full Version : [c#] eliminazione duplicati


giuseppe@85
08-09-2010, 16:18
sera a tutti,sono uo studente d'informatica del primo anno,sono alle prese con c# e con l'eliminazione di duplicati da una lista!Praticamente ho 2 liste,una in una classe Sfilata e un'altra in una classe Stilista.Ho la lista di stilisti in sfilata ed in stilista una lista di abito.Devo trovare dei duplicati attraversando entrambe le liste,ma con il mio metodo mi elimina tutti gli elementi della lista degli abiti.devo cercare tutti gli abiti con lostesso codice e rimuoverli! posto ilk codice delle classi.Vi ringrazio anticipatamente per l'aiuto.

Questo nella classe Sfilata

public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int occorrenze = 0;
foreach(Stilista stilista in listaStilisti) {
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int i = 0; i < stilista.GetListaAbiti(); i++) {
Abito nuovo = stilista.GetAbito(i);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}

mentre nella classe Stilista :

using System.Collections;

public class Stilista {

private ArrayList listaAbiti = new ArrayList();
private string nomeECognome;

public Stilista(string nomeECognome) {
this.nomeECognome = nomeECognome;
}

public Abito GetAbito(int i) {
if (i <0 || i > listaAbiti.Count) {
throw new System.ApplicationException("abito inesistente");
}
return (Abito)listaAbiti[i];
}

public override string ToString() {
string risultato = "nome e cognome stilista: "+ "|" + this.nomeECognome + "\n";
foreach (Abito abito in listaAbiti) {
risultato += abito ;
}
return risultato;
}

public int GetListaAbiti() {
return this.listaAbiti.Count;
}

public ArrayList GetLista() {
return this.listaAbiti;
}

public void AddAbito(Abito abito) {
this.listaAbiti.Add(abito);
}



public void Remove(Abito abito) {
this.listaAbiti.Remove(abito);
}


}
}

infine nella classe Abito


public class Abito {

private int codice;
private string descrizione;
private double costo;
private Modella modella;

public Abito() {}


public int Codice {
get { return codice;}
}

public override string ToString() {
return " abito: " + " codice " + " | " + " descrizione " + " | " + " costo " + " | " + " modella "+
"\n" + " " + this.codice + " | " + this.descrizione +" | " + this.costo + " | " + this.modella +"\n";
}

public void SetCodice(int codice) {
this.codice = codice;
}

public int GetCodice() {
return this.codice;
}

public void SetDescrizione(string descrizione) {
this.descrizione = descrizione;
}

public void SetCosto(double costo) {
this.costo = costo;
}

public void SetModella (Modella modella) {
this.modella = modella;
}


}
}

MEMon
08-09-2010, 18:33
sera a tutti,sono uo studente d'informatica del primo anno,sono alle prese con c# e con l'eliminazione di duplicati da una lista!Praticamente ho 2 liste,una in una classe Sfilata e un'altra in una classe Stilista.Ho la lista di stilisti in sfilata ed in stilista una lista di abito.Devo trovare dei duplicati attraversando entrambe le liste,ma con il mio metodo mi elimina tutti gli elementi della lista degli abiti.devo cercare tutti gli abiti con lostesso codice e rimuoverli! posto ilk codice delle classi.Vi ringrazio anticipatamente per l'aiuto.

Questo nella classe Sfilata

public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int occorrenze = 0;
foreach(Stilista stilista in listaStilisti) {
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int i = 0; i < stilista.GetListaAbiti(); i++) {
Abito nuovo = stilista.GetAbito(i);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}

mentre nella classe Stilista :

using System.Collections;

public class Stilista {

private ArrayList listaAbiti = new ArrayList();
private string nomeECognome;

public Stilista(string nomeECognome) {
this.nomeECognome = nomeECognome;
}

public Abito GetAbito(int i) {
if (i <0 || i > listaAbiti.Count) {
throw new System.ApplicationException("abito inesistente");
}
return (Abito)listaAbiti[i];
}

public override string ToString() {
string risultato = "nome e cognome stilista: "+ "|" + this.nomeECognome + "\n";
foreach (Abito abito in listaAbiti) {
risultato += abito ;
}
return risultato;
}

public int GetListaAbiti() {
return this.listaAbiti.Count;
}

public ArrayList GetLista() {
return this.listaAbiti;
}

public void AddAbito(Abito abito) {
this.listaAbiti.Add(abito);
}



public void Remove(Abito abito) {
this.listaAbiti.Remove(abito);
}


}
}

infine nella classe Abito


public class Abito {

private int codice;
private string descrizione;
private double costo;
private Modella modella;

public Abito() {}


public int Codice {
get { return codice;}
}

public override string ToString() {
return " abito: " + " codice " + " | " + " descrizione " + " | " + " costo " + " | " + " modella "+
"\n" + " " + this.codice + " | " + this.descrizione +" | " + this.costo + " | " + this.modella +"\n";
}

public void SetCodice(int codice) {
this.codice = codice;
}

public int GetCodice() {
return this.codice;
}

public void SetDescrizione(string descrizione) {
this.descrizione = descrizione;
}

public void SetCosto(double costo) {
this.costo = costo;
}

public void SetModella (Modella modella) {
this.modella = modella;
}


}
}
Usa il tag CODE altrimenti il tuo codice è illeggibile.

Nel secondo for devi ovviamente saltare l'indice che stai confrontando, altrimenti quello darà sempre esito positivo.

giuseppe@85
08-09-2010, 19:59
public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int pos = 0;
int occorrenze = 0;
for (int i = 0 ; i < listaStilisti.Count; i++) {
Stilista stilista = this.GetStilista(i);
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int c = 0; c < stilista.GetListaAbiti(); c++) {
Abito nuovo = stilista.GetAbito(pos);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}
ho fatto così,ma mi elimina tutti e 4 gli abiti!

MEMon
08-09-2010, 20:05
ho fatto così,ma mi elimina tutti e 4 gli abiti!

Per "usa il tag CODE" intendo che devi usare il tag CODE con all'interno codice correttamente INDENTATO! Altrimenti è illeggibile.

giuseppe@85
08-09-2010, 20:09
Usa il tag CODE altrimenti il tuo codice è illeggibile.

Nel secondo for devi ovviamente saltare l'indice che stai confrontando, altrimenti quello darà sempre esito positivo.

grazie 1000!ma nn va lo stesso!

giuseppe@85
08-09-2010, 20:11
Per "usa il tag CODE" intendo che devi usare il tag CODE con all'interno codice correttamente INDENTATO! Altrimenti è illeggibile.

public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int pos = 0;
int occorrenze = 0;
for (int i = 0 ; i < listaStilisti.Count; i++) {
Stilista stilista = this.GetStilista(i);
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int c = 0; c < stilista.GetListaAbiti(); c++) {
Abito nuovo = stilista.GetAbito(pos);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}

MEMon
08-09-2010, 20:12
grazie 1000!ma nn va lo stesso!


public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int occorrenze = 0;
foreach(Stilista stilista in listaStilisti) {
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int i = 0; i < stilista.GetListaAbiti(); i++) {
if(i==j) continue; // bastava aggiungere questo
Abito nuovo = stilista.GetAbito(i);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}


certo che va... è che hai sbagliato a modificarlo, prova così.

giuseppe@85
08-09-2010, 20:19
public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int occorrenze = 0;
foreach(Stilista stilista in listaStilisti) {
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int i = 0; i < stilista.GetListaAbiti(); i++) {
if(i==j) continue; // bastava aggiungere questo
Abito nuovo = stilista.GetAbito(i);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}


certo che va... è che hai sbagliato a modificarlo, prova così.

purtroppo non va,ho appena incollato il codice,mi da occorrenze 0 e nn elimina nulla.I codici uguali li ho caricati da file!gli faccio stampare i dati prima e dopo l'eliminazione!grz ancora!

MEMon
08-09-2010, 20:23
purtroppo non va,ho appena incollato il codice,mi da occorrenze 0 e nn elimina nulla.I codici uguali li ho caricati da file!gli faccio stampare i dati prima e dopo l'eliminazione!grz ancora!


public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int occorrenze = 0;
foreach(Stilista stilista in listaStilisti) {
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int i = 0; i < stilista.GetListaAbiti(); i++) {
System.out.println(i+" -> "+j+" ["+abito.Codice+"]["+nuovo.Codice+"]");
if(i==j) continue; // bastava aggiungere questo
Abito nuovo = stilista.GetAbito(i);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}


Prova ad usare questo, poi posta qui cosa ti viene stampato in console.

giuseppe@85
08-09-2010, 20:40
public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int occorrenze = 0;
foreach(Stilista stilista in listaStilisti) {
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int i = 0; i < stilista.GetListaAbiti(); i++) {
System.out.println(i+" -> "+j+" ["+abito.Codice+"]["+nuovo.Codice+"]");
if(i==j) continue; // bastava aggiungere questo
Abito nuovo = stilista.GetAbito(i);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}


Prova ad usare questo, poi posta qui cosa ti viene stampato in console.

mi stampa 0---->0 [35877]
0---->0 [75557]
0---->0 [58974]
0---->0 [35877]

nuovo.Codice nn lo stampa;

public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int occorrenze = 0;
foreach(Stilista stilista in listaStilisti) {
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
for(int i = 0; i < stilista.GetListaAbiti(); i++) {
System.Console.WriteLine(i+" -> "+j+" ["+abito.Codice+"]["+"]");
if(i==j) continue; // bastava aggiungere questo
Abito nuovo = stilista.GetAbito(i);
System.Console.WriteLine(" Nuovo " + nuovo.Codice);
if (abito.Codice == nuovo.Codice) {
stilista.Remove(nuovo);
occorrenze ++;
}
}
}
}
return occorrenze;
}

MEMon
08-09-2010, 20:44
Si beh ovvio che non lo stampa, lo crea dopo! Correggi.
Però come mai i e j non vengono incrementati?

giuseppe@85
08-09-2010, 20:58
[Si beh ovvio che non lo stampa, lo crea dopo! Correggi.
Però come mai i e j non vengono incrementati?[/QUOTE]

public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int pos = 0;
int occorrenze = 0;
for(int k = 0; k < listaStilisti.Count; k++) {
Stilista stilista = this.GetStilista(k);
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
System.Console.WriteLine(stilista.GetAbito(j).Codice);
System.Console.WriteLine(stilista.GetAbito(pos).Codice);
if (stilista.GetAbito(j).Codice == stilista.GetAbito(pos).Codice) {
System.Console.WriteLine(" " + ""+ j + "" + "");
pos = j;
occorrenze ++;
stilista.Remove(stilista.GetAbito(pos));
}
}
}
return occorrenze;
}

ho fatto così e mi stampa gli stessi codici sia per j che per pos;quindi come temevo mi elimina tutti perkè analizza se stesso; strano nemmno così mi incrementa la j,mi stampa zero sempre;avevo corretto e nn lo stampava ugualmente!

giuseppe@85
08-09-2010, 21:08
[Si beh ovvio che non lo stampa, lo crea dopo! Correggi.
Però come mai i e j non vengono incrementati?

public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int pos = 0;
int occorrenze = 0;
for(int k = 0; k < listaStilisti.Count; k++) {
Stilista stilista = this.GetStilista(k);
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
System.Console.WriteLine(stilista.GetAbito(j).Codice);
System.Console.WriteLine(stilista.GetAbito(pos).Codice);
if (stilista.GetAbito(j).Codice == stilista.GetAbito(pos).Codice) {
System.Console.WriteLine(" " + ""+ j + "" + "");
pos = j;
occorrenze ++;
stilista.Remove(stilista.GetAbito(pos));
}
}
}
return occorrenze;
}

ho fatto così e mi stampa gli stessi codici sia per j che per pos;quindi come temevo mi elimina tutti perkè analizza se stesso; strano nemmno così mi incrementa la j,mi stampa zero sempre;avevo corretto e nn lo stampava ugualmente![/QUOTE]

la variabile k la incrementa j no,strano!

sneeze
08-09-2010, 22:23
mamma mia che confusione,
rendi pubblica la listaAbiti della classe stilista o costruisci un metodo che te la torni come list<Abito> (meglio ancora) e poi usa un pò di linq.....

var abiti = listaStilisti[k].listaAbiti.ToArray().Cast<Abito>();
var codici = abiti.Select(i => i.Codice).Distinct().ToList();
var abitiSenzaDoppioni = codici.Select(codice => abiti.First(i => i.Codice == codice)).ToList();

abitiSenzaDoppioni è già formata da gli abiti corretti esclusi i doppioni.

p.s. A fare le cose fatte giuste dovresti implementare l'interfaccia IComparable nella tua classe Abito e overridare il metodo isEquals (mi pare si chiami così non ho tempo di controllare), così facendo potresti chiamare direttamente StilistaPippo.listaAbiti.Distinct().ToList(); e avresti fatto il tutto con una riga di codice.......... non male eh?

giuseppe@85
09-09-2010, 09:40
mamma mia che confusione,
rendi pubblica la listaAbiti della classe stilista o costruisci un metodo che te la torni come list<Abito> (meglio ancora) e poi usa un pò di linq.....

var abiti = listaStilisti[k].listaAbiti.ToArray().Cast<Abito>();
var codici = abiti.Select(i => i.Codice).Distinct().ToList();
var abitiSenzaDoppioni = codici.Select(codice => abiti.First(i => i.Codice == codice)).ToList();

abitiSenzaDoppioni è già formata da gli abiti corretti esclusi i doppioni.

p.s. A fare le cose fatte giuste dovresti implementare l'interfaccia IComparable nella tua classe Abito e overridare il metodo isEquals (mi pare si chiami così non ho tempo di controllare), così facendo potresti chiamare direttamente StilistaPippo.listaAbiti.Distinct().ToList(); e avresti fatto il tutto con una riga di codice.......... non male eh?

grazie mille,il tuo metodo è molto valido!Però purtroppo devo farlo diciamo "manualmente",nn posso utilizzare metodi particolari!

Kralizek
09-09-2010, 10:06
anche senza voler usare Linq perché é un compito scolastico, implementare l'interfaccia IEquatable<T> é perfettamente in linea con l'esercizio semplicemente perché stai spostando gran parte del carico della logica dalla funzione alla definizione dell'oggetto stesso. dopotutto "individuare le responsabilitá delle entitá coinvolte" dovrebbe essere uno degli obiettivi di un corso di programmazione ad oggetti.

una volta implementata questa interfaccia, puoi riscrivere la tua funzione in modo da usare il metodo Equals.

PS: IComparable<T> serve per l'ordinamento, non per la distinzione.

giuseppe@85
09-09-2010, 16:31
grazie a tutti per i suggerimenti!ho risolto!

sneeze
09-09-2010, 18:33
anche senza voler usare Linq perché é un compito scolastico, implementare l'interfaccia IEquatable<T> é perfettamente in linea con l'esercizio semplicemente perché stai spostando gran parte del carico della logica dalla funzione alla definizione dell'oggetto stesso. dopotutto "individuare le responsabilitá delle entitá coinvolte" dovrebbe essere uno degli obiettivi di un corso di programmazione ad oggetti.

una volta implementata questa interfaccia, puoi riscrivere la tua funzione in modo da usare il metodo Equals.

PS: IComparable<T> serve per l'ordinamento, non per la distinzione.

Si come ho scritto non mi ricordavo con esattezza. Il nome corretto dell'interfaccia a cui facevo riferimento è IEqualityComparer<T> che è possibile implementare e passare al metodo distinct, in alternativa è possibile overridare Equals appunto e GetHashCode.

Ad ogni modo non vedo perchè non usare Linq in un compito scolastico... quand'è che cominceranno insegnanti ed affini a mettere da parte la non-voglia di aggiornarsi e a favorire linguaggi e modi di programmare nuovi ed efficenti?
Linq è una vera rivoluzione in ambito c# e net in generale (e non solo). Un vero gioiellino di questo linguaggio. Si sta radicando in ogni ambito del .net: dall'accesso al dato, all'interrogazione di dati in memoria, all'interrogazione di file gerarchici (xml in primis) ecc ecc...
Inoltre si porta dietro automaticamente lambda expression, extension method, anonymoustype, collection initializer, array initializer tutte cose che non fa per niente male imparare. Per non parlare del fatto che forma il programmatore a scrivere necessariamente codice "fluent" e a COMPILARE le query che poi lancerà.
Non capisco davvero questo odio verso quello che c'è di nuovo e di valido. Ce ne fossero tutti i giorni di implementazioni come LinQ.

Kralizek
09-09-2010, 19:55
tranquillo non me lo devi vendere... ci ho scritto un motore di ricerca basato su linq to objects e programmazione funzionale :)

giuseppe@85
10-09-2010, 11:44
Si come ho scritto non mi ricordavo con esattezza. Il nome corretto dell'interfaccia a cui facevo riferimento è IEqualityComparer<T> che è possibile implementare e passare al metodo distinct, in alternativa è possibile overridare Equals appunto e GetHashCode.

Ad ogni modo non vedo perchè non usare Linq in un compito scolastico... quand'è che cominceranno insegnanti ed affini a mettere da parte la non-voglia di aggiornarsi e a favorire linguaggi e modi di programmare nuovi ed efficenti?
Linq è una vera rivoluzione in ambito c# e net in generale (e non solo). Un vero gioiellino di questo linguaggio. Si sta radicando in ogni ambito del .net: dall'accesso al dato, all'interrogazione di dati in memoria, all'interrogazione di file gerarchici (xml in primis) ecc ecc...
Inoltre si porta dietro automaticamente lambda expression, extension method, anonymoustype, collection initializer, array initializer tutte cose che non fa per niente male imparare. Per non parlare del fatto che forma il programmatore a scrivere necessariamente codice "fluent" e a COMPILARE le query che poi lancerà.
Non capisco davvero questo odio verso quello che c'è di nuovo e di valido. Ce ne fossero tutti i giorni di implementazioni come LinQ.

public int RimuoviDoppioni() {
if (listaStilisti.Count == 0) {
throw new System.ApplicationException("lista stilisti vuota");
}
int pos = 0;
int occorrenze = 0;
for (int z = 0; z<listaStilisti.Count; z++) {
Stilista stilista = this.GetStilista(z);
for (int j = 0; j < stilista.GetListaAbiti();j++) {
Abito abito = stilista.GetAbito(j);
bool trovato = false;
for (int m = 0; m <listaStilisti.Count; m ++) {
Stilista stilista2 = this.GetStilista(m);
for(int c = 0; c < stilista2.GetListaAbiti(); c++) {
Abito nuovo = stilista2.GetAbito(pos);
if (abito.Codice == nuovo.Codice) {
if (trovato) {
stilista2.Remove(nuovo);
occorrenze ++;
} else {
trovato = true;
}
}
}
}
}
}
return occorrenze;
}

Alla fine ho risolto così grazie anke all'aiuto di un utente su un altro forum!
Tu hai fortemente ragione,ma io ho seguito un corso che si chiama oggetti 1 che ti da le basi e ti fa capire il funzionamentodella programmazione ad ogetti!Da ottobre seguirò oggetti 2 con il quale,almeno credo,inizierò ad imparare meglio i trucchetti della programmazione,e spero anke quello che hai menzionato!cmq ci tenevo a dirvi che siete davvero molto bravi,i miei complimenti!grazie ancora x i vostri suggerimenti!!

sneeze
10-09-2010, 12:32
tranquillo non me lo devi vendere... ci ho scritto un motore di ricerca basato su linq to objects e programmazione funzionale :)

Non mi riferivo a te... era già evidente che sapevi di cosa stavi parlando. Mi riferivo a una certa mentalità che impera purtroppo....