Laden...

Wie finde ich Duplikate in einer Objekt-Liste anhand von mehreren, aber nicht allen, Properties?

Erstellt von ill_son vor 3 Jahren Letzter Beitrag vor 3 Jahren 894 Views
I
ill_son Themenstarter:in
227 Beiträge seit 2009
vor 3 Jahren
Wie finde ich Duplikate in einer Objekt-Liste anhand von mehreren, aber nicht allen, Properties?

Hallo,

ich habe eine IEnumerable mit Objekten:


public class MyObject
{
    public int Prop1 { get; } 
    public string Prop2 { get; }
    public int Prop3 { get; }
}

...
//schnipp schnapp
...

IEnumerable<MyObject> MyEnumerable;

Jetzt möchte ich alle Duplikate finden, wobei Einträge als Duplikat gelten, wenn Prop1 und Prop2 gleich sind, Prop3 ist für den Vergleich uninteressant.

Nun liefert mir


var dublicates = list.GroupBy(e => new { e.Prop1, e.Prop2 }).Where(g => g.Count() > 1).Select(g => g.Key);

ein IEnumerabel mit dem anonymen Typen {Prop1, Prop2}, ich benötige aber eine Auflistung mit den ganzen Objekten. Wie kann ich das anstellen?

Grüße, Alex

Final no hay nada más

T
2.219 Beiträge seit 2008
vor 3 Jahren

Warum machst du ein GroupBy mit einem neuen Typen?
Mach doch GroupBy und dann ThenBy, dann bleibt dein Typ auch erhalten.
Danach sollte deine Daten passen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

I
ill_son Themenstarter:in
227 Beiträge seit 2009
vor 3 Jahren

Hallo T-Virus,

Danke für deine Antwort. Ich muss gestehen, dass das Propblem meine aktuellen Linq-Kenntnisse etwas übersteigt. Wie müsste denn dann der Parameter für GroupBy aussehen?

Final no hay nada más

T
2.219 Beiträge seit 2008
vor 3 Jahren

Schau in die Doku, der Aufbau ist nicht anders als bei Where.

GroupBy
ThenBy

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

W
955 Beiträge seit 2010
vor 3 Jahren

GroupBy ist overkill für Duplikate. Du kannst doch einfach Distinct() verwenden. Schau mal ob er es berücksichtigt wenn du Equals überschreibst oder IEquatable<T> implementierst. Sicherlich gibt es auch irgendwo ne Lib welche Linq um DistinctBy erweitert.

T
2.219 Beiträge seit 2008
vor 3 Jahren

@witte
Wie soll Distinct dabei helfen die Dublikatte zu ermitteln?
Dadurch werden diese entfernt, was aber nicht der Sinn der Umsetzung ist.
Der TE will ja explizit nur die Einträge, die anhand der Properties mehr als einmal vorhanden sind.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.806 Beiträge seit 2008
vor 3 Jahren

Also davon abgesehen, dass dieses Thema quasi Linq-Alltag ist und sicherlich über Google hunderte Treffer sich finden lassen, seh ich das auch so, dass ein GroupBy (in der Laufzeit) völliger Overkill ist.

Über ein GroupBy könnte man anhand der Properties einfach den GroupKey setzen; ein ThenBy ist gar nicht notwendig.

var duplicates = mySource
    .GroupBy(e => new { e.Prop1, e.Prop2 })
    .Where(g => g.Count() > 1)
    .SelectMany(e => e)
    .ToList();

Aber eigentlich sauberer dürfte das ganze einfach über nen IEqualityComparer gehen.
Der IEqualityComparer beachtet dabei nur die gewünschten Properties und über nen HashSet-Compare lassen sich duplikate sehr schnell (viel schneller als GroupBy) und übersichtlich finden.
Gerade wenn man Linq nicht verstanden hat, dann bringt es ja nichts, wenn man damit arbeitet und es nicht versteht.

Ich hab da aus den Tiefen meiner Snippets auch noch was

  public static IEnumerable<TSource> FindDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer)
  {
    var set = new HashSet<TKey>(comparer);
    return source.Where(item => !set.Add(selector(item)));
  }

Man kann aber auch einfach Except verwenden und den Comparer verwenden - gleiches Prinzip.

W
955 Beiträge seit 2010
vor 3 Jahren

@T-Virus
Hmh, mir ist eigentlich gar nicht klar was der TE überhaupt damit will. Meistens ja um diese zu entfernen. Daher meine Antwort.

T
2.219 Beiträge seit 2008
vor 3 Jahren

@Abt
Ist natürlich ein besserer Ansatz 😃

@witte
Hängt halt vom Kontext ab.
Kann auch sein, dass er eine Liste aus einer Datei einliest und Dubletten suchen und anzeigen muss.
Dann macht es schon Sinn, diese einfach zu ermitteln und dann nur noch anzuzeigen.
Aus diesem Kontext habe ich es betrachtet und bin auch erst einmal davon ausgegangen, da der TE ja explizit nach den Dublikaten suchte.
Zum reinen entfernen wäre dann natürlich Distinct sinnvoller. 😉

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

I
ill_son Themenstarter:in
227 Beiträge seit 2009
vor 3 Jahren

@T-Virus
Hmh, mir ist eigentlich gar nicht klar was der TE überhaupt damit will. Meistens ja um diese zu entfernen. Daher meine Antwort.

Ich möchte die Einträge erstmal markieren, um sie in der Anzeige hervorzuheben.

@all: Danke für die Hilfe.

Grüße, Alex

Final no hay nada más