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?

6voto

Reza Jenabi Punkte 3356

Wenn Sie Schleppunterricht haben Product y Customer und wir wollen doppelte Einträge aus ihrer Liste entfernen

public class Product
{
    public int Id { get; set; }
    public string ProductName { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string CustomerName { get; set; }

}

Sie müssen eine generische Klasse in der folgenden Form definieren

public class ItemEqualityComparer<T> : IEqualityComparer<T> where T : class
{
    private readonly PropertyInfo _propertyInfo;

    public ItemEqualityComparer(string keyItem)
    {
        _propertyInfo = typeof(T).GetProperty(keyItem, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
    }

    public bool Equals(T x, T y)
    {
        var xValue = _propertyInfo?.GetValue(x, null);
        var yValue = _propertyInfo?.GetValue(y, null);
        return xValue != null && yValue != null && xValue.Equals(yValue);
    }

    public int GetHashCode(T obj)
    {
        var propertyValue = _propertyInfo.GetValue(obj, null);
        return propertyValue == null ? 0 : propertyValue.GetHashCode();
    }
}

dann können Sie doppelte Einträge in Ihrer Liste entfernen.

var products = new List<Product>
            {
                new Product{ProductName = "product 1" ,Id = 1,},
                new Product{ProductName = "product 2" ,Id = 2,},
                new Product{ProductName = "product 2" ,Id = 4,},
                new Product{ProductName = "product 2" ,Id = 4,},
            };
var productList = products.Distinct(new ItemEqualityComparer<Product>(nameof(Product.Id))).ToList();

var customers = new List<Customer>
            {
                new Customer{CustomerName = "Customer 1" ,Id = 5,},
                new Customer{CustomerName = "Customer 2" ,Id = 5,},
                new Customer{CustomerName = "Customer 2" ,Id = 5,},
                new Customer{CustomerName = "Customer 2" ,Id = 5,},
            };
var customerList = customers.Distinct(new ItemEqualityComparer<Customer>(nameof(Customer.Id))).ToList();

Dieser Code entfernt doppelte Einträge durch Id Wenn Sie doppelte Elemente anhand anderer Eigenschaften entfernen möchten, können Sie die nameof(YourClass.DuplicateProperty) même nameof(Customer.CustomerName) entfernen Sie dann doppelte Einträge durch CustomerName Eigentum.

6voto

Motti Punkte 104854

Wenn Sie sich nicht um die Reihenfolge kümmern, können Sie die Elemente einfach in eine HashSet wenn Sie tun Wenn Sie die Reihenfolge beibehalten wollen, können Sie so vorgehen:

var unique = new List<T>();
var hs = new HashSet<T>();
foreach (T t in list)
    if (hs.Add(t))
        unique.Add(t);

Oder die Linq-Methode:

var hs = new HashSet<T>();
list.All( x =>  hs.Add(x) );

Bearbeiten: El HashSet Methode ist O(N) Zeit und O(N) Platz beim Sortieren und dann eindeutig machen (wie von @ vorgeschlagen) lassvk und andere) ist O(N*lgN) Zeit und O(1) Platz, so dass es für mich nicht so klar ist (wie es auf den ersten Blick schien), dass die Sortiermethode minderwertig ist (ich entschuldige mich für die vorübergehende Herabstufung...)

4voto

Chris Punkte 67

Es wäre vielleicht einfacher, dafür zu sorgen, dass keine Duplikate in die Liste aufgenommen werden.

if(items.IndexOf(new_item) < 0) 
    items.add(new_item)

1 Stimmen

Ich mache es derzeit so, aber je mehr Einträge Sie haben, desto länger dauert die Überprüfung auf Duplikate.

0 Stimmen

Ich habe hier das gleiche Problem. Ich benutze die List<T>.Contains Methode, aber mit mehr als 1.000.000 Einträgen. Dieser Prozess verlangsamt meine Anwendung. Ich verwende eine List<T>.Distinct().ToList<T>() stattdessen zuerst.

0 Stimmen

Diese Methode ist sehr langsam

3voto

Moctar Haiz Punkte 141

Eine einfache, intuitive Umsetzung:

public static List<PointF> RemoveDuplicates(List<PointF> listPoints)
{
    List<PointF> result = new List<PointF>();

    for (int i = 0; i < listPoints.Count; i++)
    {
        if (!result.Contains(listPoints[i]))
            result.Add(listPoints[i]);
        }

        return result;
    }

0 Stimmen

Auch diese Methode ist langsam. Erzeugt eine neue Liste.

3voto

Infosunny Punkte 438

HashSet verwenden: list = new HashSet<T>(list).ToList();

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