Laden...

Sehr große List<> objekte vergleichen

Erstellt von DragonTHB vor 2 Jahren Letzter Beitrag vor 2 Jahren 287 Views
D
DragonTHB Themenstarter:in
4 Beiträge seit 2013
vor 2 Jahren
Sehr große List<> objekte vergleichen

Guten Tag,

Ich habe zwei List<> Objekte und ich möchte vergleichen, ob Elemente vom Objekt zwei im Objekt eins vorhanden ist. Ich mache das ganz normal über die "Contains" methode.


foreach (FileInfo fi in Datensatz1.Dateien_liste)
            {
                if(!Datensatz2.Dateien_liste.Contains(fi))
                {
                    Datensatz3.addFileInfo(fi);
                }
            }

Das Problem ist, dass Objekt eins und Objekt zwei jeweils 1,3 Millionen Elemente enthalten und mein PC somit ca 1,69*10^12 vergleiche machen muss, was antscheinend sehr sehr lange dauert. Jetzt bin ich am überlegen, wie ich diesen Vorgang beschleunigen kann. Mir ist aufgefallen, dass meine CPU bei 12% Auslastung rumdümpelt. Ich habe mir überlegt diesen Vergleich in mehrere Tasks aufzuteilen. Ich würde gucken wie hoch die Systemleistung und so lange neue Tasks starten, bis die Systemleistung 100% beträgt. Wobei jeder Task halt immer nur 10.000 Elemente vergleicht oder so.

Fällt einem von euch vielleicht etwas besseres ein?

16.835 Beiträge seit 2008
vor 2 Jahren

Riecht schon fischig, dass Du überhaupt eine Liste mit so vielen Einträgen hast.
Muss das sein? Gerade bei Dateien macht man sowas absolut nicht, weil das FileInfo Objekt sehr sehr teuer ist und auch immer ein offenes Datei-Handle hat, was Betriebssystemressourcen reserviert.
Deine Anwendung hat also Millionen von Handles, obwohl sie das gar nich braucht - nich so dolle 🙂

Dazu ist die List nicht für so große Mengen als Vergleichsressource gedacht.
Das HashSet (O(1)) muss beim Zugriff auf Einträge im Gegensatz zur List (ich glaube O(n)) nicht auf den Enumerator zugreifen.

Weiterhin musst Du definieren, woran das Objekt unterschieden werden kann.
Je einfacher die Unterscheidungsprüfung, desto schneller die Suche.

T
2.224 Beiträge seit 2008
vor 2 Jahren

Je nachdem was du von dem FileInfo brauchst, kannst du ggf. auch eine eigene Klasse anlegen und nur die nötigsten Informationen übernehmen.
Ebenfalls kannst du bei der Verwaltung der Einträge auch ein Dictionary nehmen.
Wenn du z.B. den Pfad oder nur den Dateinamen zur Suche brauchst, kannst du diesen als Key nehmen.
Über die Values kannst du dir dann auch immer eine Liste anlegen und befüllen.

Der Vorteil aus der Kombination ist neben dem einsparen der Handles auch das aussparen von unnötigen Daten was bei der Menge an Einträgen auch einiges an Speicher spart.
Ist das richtig, dass du fehlende Einträge aus Datensatz1 an Datensatz3 hängst, wenn diese in Datensatz2 nicht vorhanden sind?
Sieht auf den ersten Blick aus, wie falsch angehangen.

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.

A
2 Beiträge seit 2021
vor 2 Jahren

Huhu,

du kannst die Listen glaube ich mit Union, Interselect, Except vergleichen...

Hier ein Beispiel, das wird nicht funktionieren, aber vom Grundsatz sollte es Klarheit schaffen.

Siehe auch hier:



        public static List<md5list> md5lines1 = new List<md5list>();
        public static List<md5list> md5lines2 = new List<md5list>();
            

            // Step 1: Create a union list from the first and the second (only single entries. Duplicates will be removed automatically)
            var unionList = md5lines1.Union(md5lines2, new DoCompare());
            // Step 2: Create a list with the entries, which are in both lists 
            var intersectList = md5lines1.ToList().Intersect(md5lines2, new DoCompare());
            // Step 3: Get the entries which only in the union list and not in the intersect list
            var exceptList = unionList.Except(intersectList);
            // Step 4: Create a list with entries only in file1
            var onlyFile1 = exceptList.Except(md5lines2);
            // Step 4: Create a list with entries only in file2
            var onlyFile2 = exceptList.Except(md5lines1);

        public class md5list
        {
            public string Hash { get; set; }

            public string Path { get; set; }

            public override string ToString()
            {
                return "Hash: " + Hash + " Path: " + Path;
            }
        }

        public class DoCompare : IEqualityComparer<md5list>
        {
            public bool Equals(md5list md5lines1, md5list md5lines2)
            {
                if (md5lines1.Hash == md5lines2.Hash && md5lines1.Path == md5lines2.Path)
                {
                    return true;
                }
                return false;
            }
            public int GetHashCode(md5list obj)
            {
                return obj.Hash.GetHashCode();
            }

        }


Das ist denke ich die schnelle Lösung...

Ich hoffe das war jetzt nicht komplett am Thema vorbei...

Grüße,
Art