Zwei List<T> auf Unterschiede vergleichen



  • Hallo,

    ich möchte zwei Listen miteinander vergleichen und die Unterschiede aus einer Liste in eine neue Liste schreiben.
    Meine Listen haben eine unterschiedliche Anzahl an Items.

    IEnumerable<CompareItems> list1 = GetOne(); 
    IEnumerable<CompareItems> list2 = GetTwo(); 
    
    List<CompareItems> listDifference = new List<CompareItems>();
    //List<string> list = new List<string>();
    
    var differenceQuery = list2.Except(list1);
    
    foreach (var newItems in differenceQuery)
            {
                listDifference.Add(newItems);
                //list.Add(newParts.PartNumber);
            }
    
    return differenceQuery;
    //return list;
    

    Ich habe es einmal als Rückgabe mit meiner eigenen Klasse versucht und einmal über einen string.
    Beides mal enthät mein Rückgabewert aber entwerder nur die Items aus list1 oder aus list2 (je nachdem wie rum ich .Except ausführe).
    Aber ich erhalte nie irgendwelche Unterschiede?? 😕

    Meine Klasse CompareItems hat zwei Felder (id, content), beides string.
    Wobei id jeweils (bei beiden List) gefüllt wird und der content bei beiden List null ist.

    Hoffe Ihr könnt mir helfen?! Danke! 🙂



  • Mit Except() erhälst du alle Items aus Liste1 exclusive bzw. ohne die Items aus Liste2. Oder anders formuliert, Except sucht in Liste1 Items die identisch sind mit Items aus Liste2 und verwirft diese dann im Ergebnis.

    So hast du alle gleichen Items entfernt. Mehr aber auch nicht. Du musst in einer Schleife über beide Listen iterieren und diese vergleichen. In etwa so:

    IEnumerable<CompareItems> list1 = GetOne(); 
    IEnumerable<CompareItems> list2 = GetTwo(); 
    
    List<CompareItems> listDifference = new List<CompareItems>();
    
    foreach (var item in list1)
    {
        var result= list2.FirstOrDefault(o => o.id == item.id);
        if(result == null)
        {
           listDifference.Add(item);
        }
    }
    


  • Super danke!

    Hätte aber nochmals eine Frage.
    Ich binde die Daten an eine List<CompareItems> und binde diese an einen DataGridView.

    Nun möchte ich gerne (per Buttonclick), dass Items auch wieder aus der Liste entfernt werden können.

    private void gridCompareItems_CellClick(object sender, DataGridViewCellEventArgs e)
            {
                if (e.ColumnIndex == 2)
                {
                    CompareItems itemToRemove = new CompareItems();
                    itemToRemove.Id = gridCompareItems[0, e.RowIndex].Value.ToString();
    
                    listItemsToSave.Remove(itemToRemove);
    
                    gridCompareItems.DataSource = null;
                    gridCompareItems.Columns.Clear();
                   gridCompareItems.DataSource = listItemsToSave;
                }
            }
    

    Es wird aber nichts entfernt?! 😕



  • Ich habe nun meine Abfrage nochmals ein wenig umgeändert bzw. auch noch gesucht, aber kann mein Problem nun leider immer noch nicht lösen:

    private static List<items> ohneDoppelte(List<items> stringList)
            {
                // Dictionary das mitzählt, wie oft ein Element bereits vorkam
                Dictionary<items, int> stringOccurence = new Dictionary<items, int>();
                // Mit 0 initialisieren
                foreach (items s in stringList)
                    stringOccurence[s] = 0;
    
                // Kopie erzeugen
                List<items> result = new List<items>(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;
            }
    

    So habe ich ein Beispiel im Netz gefunden und an meine eigene Klasse <items> angepasst.
    Leider werden Duplikate immer noch nicht entfernt.

    Meine Klasse <items>:
    -id
    -content
    -group
    -name

    Meine Klasse hat mehrere Felder, wobei ich gerne nur auf ein Feld (id) die Duplikate prüfen möchte. Wie kann ich das machen?



  • Implementier das Interface IEquatable<T> und mach dort den Vergleich auf deine ID Property. Danach rufst du einfach .Distinct auf deine Liste auf und die Sache hat sich erledigt. Da brauchst du kein Dictionary.



  • @Firefighter
    Klappt wunderbar! Danke für den Tipp! 👍


Log in to reply