Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
doppelte Werte einer Liste löschen

Moderationshinweis von herbivore (11.08.2010 - 10:15:58):

Dies ist ein Thread, auf den aus der FAQ verwiesen wird. Bitte keine weitere Diskussion, sondern nur wichtige Ergänzungen und diese bitte knapp und präzise. Vielen Dank!

impact_1991
myCSharp.de - Member



Dabei seit:
Beiträge: 44
Herkunft: Eichsfeld

Themenstarter:

doppelte Werte einer Liste löschen

beantworten | zitieren | melden

Hallo ich wollte alle Werte einer doppelten Liste lösche, weiß einer von euch, was ich falsch gemacht habe und wie es besser geht ?
Hab schon gegoogelt aber nichts passendes gefunden


        private List<string> doppelte_finden(List<string> Liste_string)
        {
            for (int i = 0; i < Liste_string.Count; i++)
            {
                for (int j = 0; j < Liste_string.Count; j++)
                {
                    if (Liste_string[i] == Liste_string[j]) // Fehler
                    {
                        Liste_string.Remove(Liste_string[j]);
                    }
                }
            }
            return Liste_string;
        }

Gruß impact_1991
private Nachricht | Beiträge des Benutzers
a957m
myCSharp.de - Member



Dabei seit:
Beiträge: 255
Herkunft: Stuttgart

beantworten | zitieren | melden

Hi,

na was denkste was beim ersten Durchlauf passiert ?

Liste_string[0] == Liste_string[0]

Ich würde, die Elemente in einem Dictionary<string,string> sammeln. Eine foreach Schleife und bei jedem Element nachschauen, ob es schon im Dictionary enthalten ist. Das funktioniert, dann auch wenn ein Element öfter als zweimal vorkommt.

Tschüss
private Nachricht | Beiträge des Benutzers
impact_1991
myCSharp.de - Member



Dabei seit:
Beiträge: 44
Herkunft: Eichsfeld

Themenstarter:

beantworten | zitieren | melden

danke für den Vorschlag
das müsste klappen
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von impact_1991 am .
private Nachricht | Beiträge des Benutzers
tom-essen
myCSharp.de - Experte

Avatar #avatar-2140.png


Dabei seit:
Beiträge: 1928
Herkunft: NRW

beantworten | zitieren | melden

Hallo!
Zudem sollte die Liste zwingend rückwärts durchlaufen werden, sonst fällt ein Index irgendwann ins Leere, wenn man vorher was gelöscht hat.

Also bei sowas immer


for (int i = Liste_string.Count - 1; i ≥ 0; i--) ...
Nobody is perfect. I'm sad, i'm not nobody
private Nachricht | Beiträge des Benutzers
impact_1991
myCSharp.de - Member



Dabei seit:
Beiträge: 44
Herkunft: Eichsfeld

Themenstarter:

beantworten | zitieren | melden

Ich hab es jetzt so umgesetzt



 private List<string> doppelte_finden(List<string> Liste_string)
        {
            List<string> ergebnis= new List<string>();
            bool schon_vorhanden = false;
            
            for (int i = 0; i < Liste_string.Count; i++)
            {
                for (int j = 0; j < ergebnis.Count; j++)
                {
                    if (Liste_string[i] == ergebnis[j])
                    {
                        schon_vorhanden = true;
                        break;

                    }
                    
                }
                if (schon_vorhanden == false)
                {
                    ergebnis.Add(Liste_string[i]);
                    
                }
                else
                {
                    schon_vorhanden = false;
                }
            }
            return ergebnis;
        }



fals jemand etwas übersichtlicheres oder schnelleres kennt kann es gern posten

gruß impact

EDIT von herbivore: Ungünstige Lösung wegen der quadratischen Laufzeit. Erklärung und bessere Lösungen (mit linearer Laufzeit) siehe weiter unten.
private Nachricht | Beiträge des Benutzers
xxMUROxx
myCSharp.de - Member

Avatar #avatar-3236.jpg


Dabei seit:
Beiträge: 1626
Herkunft: Südtirol/Italien

beantworten | zitieren | melden

Hallo impact_1991,
aus diesem:
if(schon_vorhanden == false)
if(!schon_vorhanden)
folgt ganz schnell dies: [Tipp] Anfängerfehler == true / == false

Gruß Michael
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von xxMUROxx am .
Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1380
Herkunft: Berlin

beantworten | zitieren | melden

Hi,

Vorschlag 1:

// behält die Reihenfolge bei
private static List<string> ohneDoppelte(List<string> stringList)
{
    // Menge der strings, die bereits in der Ergebnisliste sind
    HashSet<string> strings = new HashSet<string>();
            
    // Mittels LINQ die Werte übernehmen, die vorher noch nicht vorkamen
    return stringList.Where(x => 
        {
            // wenn schon in der ErgebnisListe, dann nicht übernehmen
            if (strings.Contains(x))
            {
                return false;
            }
            // andernfalls der Menge hinzufügen und Element übernehmen
            else
            {
                strings.Add(x);
                return true;
            }
        })
        .ToList();
}

Vorschlag 2:

// ignoriert die Reihenfolge
private static List<string> ohneDoppelte(List<string> stringList)
{
    // Liste in eine Menge und wieder zurück in eine Liste umwandeln
    // (doppelte Einträge gehen verloren)
    return (new HashSet<string>(stringList)).ToList();
}

Vorschlag 3: (Annahme: RemoveAll(...) geht sequentiell in der normalen Iterationsreihenfolge durch)


// behält die Reihenfolge bei
private static List<string> ohneDoppelte(List<string> stringList)
{
    // Dictionary das mitzählt, wie oft ein Element bereits vorkam
    Dictionary<string, int> stringOccurence = new Dictionary<string, int>();
    // Mit 0 initialisieren
    foreach (string s in stringList)
        stringOccurence[s] = 0;

    // Kopie erzeugen
    List<string> result = new List<string>(stringList);
    // Alle Elemente entfernen, die vorher schonmal aufgetreten sind
    // (und dabei mitzählen, dass sie aufgetreten sind)
    result.RemoveAll(x => (stringOccurence[x]++ > 0));
    return result;
}

Ah, hier wäre noch eine vierte LINQ-Variante


// ignoriert die Reihenfolge
private static List<string> ohneDoppelte(List<string> stringList)
{
    return stringList.Distinct().ToList();
}

beste Grüße
zommi
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von zommi am .
private Nachricht | Beiträge des Benutzers
impact_1991
myCSharp.de - Member



Dabei seit:
Beiträge: 44
Herkunft: Eichsfeld

Themenstarter:

beantworten | zitieren | melden

Hy zommi,

könntest du vllt ein paar kurze kommentare dazu schreiben was du da machst?

auf jeden fall ist es sehr übersichtlich und es funktioniert.

Danke
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1380
Herkunft: Berlin

beantworten | zitieren | melden

Habe oben noch Kommentare eingefügt.

Die erste beiden und die vierte Variante nutzen die LINQ-Extensions ab .NET 3.5.
Daher hab ich noch eine Variante 3 hinzugefügt, die auch mit .NET 2.0 funktionieren sollte, da sie nur das Dictionary<,> verwendet.

Die Idee ist aber bei allen, dass eine zusätzliche Hash-basierte Collection verwendet wird, der die Eigenschaft doppelte Einträge zu entfernen inhärent ist.
Dadurch, dass die hash-basierten Collections im Idealfall einen Zugriff in O(1) ermöglichen, reduziert sich in allen Fällen die Laufzeit auf O(n), im Vergleich zum O(n^2) deiner verschachtelten Schleife.

beste Grüße
zommi
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von zommi am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo impact_1991,

auch wenn das Löschen von Duplikaten ein besonderer Spezialfall von [FAQ] Auflistungs-Elemente suchen und entfernen ist, der nach einem Dictionary/HashSet bzw. nach Linq schreit, sind in der FAQ doch einige Anmerkungen enthalten, die von grundsätzlichem Interesse sind.

herbivore
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 7572
Herkunft: Waidring

beantworten | zitieren | melden

Hallo,

siehe auch Duplikate aus IEnumerable<T> entfernen bzw. unterschiedliche Elemente holen



mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
private Nachricht | Beiträge des Benutzers