643 Stimmen

Duplikate aus einer List<T> in C# entfernen

Jeder haben eine schnelle Methode für de-Duplizierung eine generische Liste in C#?

5 Stimmen

Ist Ihnen die Reihenfolge der Elemente im Ergebnis wichtig? Dies wird einige Lösungen ausschließen.

3 Stimmen

Eine Ein-Zeilen-Lösung: ICollection<MyClass> withoutDuplicates = new HashSet<MyClass>(inputList);

0 Stimmen

Wo würde diese Methode angewendet werden?

2voto

Darkgaze Punkte 1976

Alle Antworten kopieren Listen oder erstellen eine neue Liste oder verwenden langsame Funktionen oder sind einfach nur schmerzhaft langsam.

Nach meinem Verständnis ist dies die schnellste und billigste Methode Ich weiß es (auch mit der Unterstützung eines sehr erfahrenen Programmierers, der sich auf die Optimierung der Echtzeit-Physik spezialisiert hat).

// Duplicates will be noticed after a sort O(nLogn)
list.Sort();

// Store the current and last items. Current item declaration is not really needed, and probably optimized by the compiler, but in case it's not...
int lastItem = -1;
int currItem = -1;

int size = list.Count;

// Store the index pointing to the last item we want to keep in the list
int last = size - 1;

// Travel the items from last to first O(n)
for (int i = last; i >= 0; --i)
{
    currItem = list[i];

    // If this item was the same as the previous one, we don't want it
    if (currItem == lastItem)
    {
        // Overwrite last in current place. It is a swap but we don't need the last
       list[i] = list[last];

        // Reduce the last index, we don't want that one anymore
        last--;
    }

    // A new item, we store it and continue
    else
        lastItem = currItem;
}

// We now have an unsorted list with the duplicates at the end.

// Remove the last items just once
list.RemoveRange(last + 1, size - last - 1);

// Sort again O(n logn)
list.Sort();

Die endgültigen Kosten sind:

nlogn + n + nlogn = n + 2nlogn = O(nlogn) was ziemlich nett ist.

Hinweis zu RemoveRange: Da wir den Zähler der Liste nicht einstellen und die Entfernen-Funktionen nicht verwenden können, weiß ich nicht genau, wie schnell dieser Vorgang abläuft, aber ich schätze, es ist der schnellste Weg.

2voto

Guest Punkte 21

Die Antwort von David J. ist eine gute Methode, bei der keine zusätzlichen Objekte, keine Sortierung usw. erforderlich sind. Sie kann jedoch noch verbessert werden:

for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)

Die äußere Schleife geht also für die gesamte Liste von oben nach unten, die innere Schleife jedoch von unten nach oben, "bis die Position der äußeren Schleife erreicht ist".

Die äußere Schleife stellt sicher, dass die gesamte Liste verarbeitet wird, die innere Schleife findet die tatsächlichen Duplikate, die nur in dem Teil auftreten können, den die äußere Schleife noch nicht verarbeitet hat.

Wenn Sie die innere Schleife nicht von unten nach oben ausführen möchten, können Sie die innere Schleife auch bei outerIndex + 1 beginnen lassen.

1voto

Paul Richards Punkte 1121
  public static void RemoveDuplicates<T>(IList<T> list )
  {
     if (list == null)
     {
        return;
     }
     int i = 1;
     while(i<list.Count)
     {
        int j = 0;
        bool remove = false;
        while (j < i && !remove)
        {
           if (list[i].Equals(list[j]))
           {
              remove = true;
           }
           j++;
        }
        if (remove)
        {
           list.RemoveAt(i);
        }
        else
        {
           i++;
        }
     }  
  }

1voto

Onat Korucu Punkte 746

Wenn Sie komplexe Objekte vergleichen müssen, müssen Sie ein Comparer-Objekt innerhalb der Methode Distinct() übergeben.

private void GetDistinctItemList(List<MyListItem> _listWithDuplicates)
{
    //It might be a good idea to create MyListItemComparer 
    //elsewhere and cache it for performance.
    List<MyListItem> _listWithoutDuplicates = _listWithDuplicates.Distinct(new MyListItemComparer()).ToList();

    //Choose the line below instead, if you have a situation where there is a chance to change the list while Distinct() is running.
    //ToArray() is used to solve "Collection was modified; enumeration operation may not execute" error.
    //List<MyListItem> _listWithoutDuplicates = _listWithDuplicates.ToArray().Distinct(new MyListItemComparer()).ToList();

    return _listWithoutDuplicates;
}

Angenommen, Sie haben 2 andere Klassen wie:

public class MyListItemComparer : IEqualityComparer<MyListItem>
{
    public bool Equals(MyListItem x, MyListItem y)
    {
        return x != null 
               && y != null 
               && x.A == y.A 
               && x.B.Equals(y.B); 
               && x.C.ToString().Equals(y.C.ToString());
    }

    public int GetHashCode(MyListItem codeh)
    {
        return codeh.GetHashCode();
    }
}

Und:

public class MyListItem
{
    public int A { get; }
    public string B { get; }
    public MyEnum C { get; }

    public MyListItem(int a, string b, MyEnum c)
    {
        A = a;
        B = b;
        C = c;
    }
}

0voto

user3150241 Punkte 33

Ich denke, das ist der einfachste Weg:

Erstellen Sie eine neue Liste und fügen Sie ein eindeutiges Element hinzu.

Beispiel:

        class MyList{
    int id;
    string date;
    string email;
    }

    List<MyList> ml = new Mylist();

ml.Add(new MyList(){
id = 1;
date = "2020/09/06";
email = "zarezadeh@gmailcom"
});

ml.Add(new MyList(){
id = 2;
date = "2020/09/01";
email = "zarezadeh@gmailcom"
});

 List<MyList> New_ml = new Mylist();

foreach (var item in ml)
                {
                    if (New_ml.Where(w => w.email == item.email).SingleOrDefault() == null)
                    {
                        New_ml.Add(new MyList()
                        {
                          id = item.id,
     date = item.date,
               email = item.email
                        });
                    }
                }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X