Autor |
Beitrag |
diego2k
Hält's aus hier
Beiträge: 7
|
Verfasst: Fr 20.03.09 16:02
Hallo
Habe das Problem das der Code viel zu langsam ist. Es wird die Ordnerstrucktur durchsucht und jede Datei in
einer List<string> gespeichert. Damit ist es möglich dann auch verschieden Dinge mit hilfe von FileInfo auszulesen.
Es solln mehrfach vorkommende Dateinamen ausgegeben werden.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| for (Int32 i = 0; i < couter; i++) { infos = new FileInfo(_data[i].ToString()); for (Int32 k = 0; k < couter; k++) { infos2 = new FileInfo(_data[k].ToString()); if (infos.Name.ToString() == infos2.Name.ToString()) { _return.Add(_data[k]); } } } |
Mit diesem Code geht das allerdings wesendlich schneller. Das Problem ist hier das nicht das komplette Array feld miteinander verglichen werden soll, sondern nur der Name.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| static List<string> removeDuplicates(List<string> inputList) { Dictionary<string, int> uniqueStore = new Dictionary<string, int>(); List<string> finalList = new List<string>(); foreach (String currValue in inputList) { if (!uniqueStore.ContainsKey(currValue)) { uniqueStore.Add(currValue, 0); finalList.Add(currValue); } } return finalList; } |
Ich habs mit ca 50000 Datein Probiert, der erste Code braucht dafür ewig, der 2. ein paar sec. Moderiert von Christian S.: Topic aus C# - Die Sprache verschoben am Fr 20.03.2009 um 18:14
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 20.03.09 16:10
Woher kommt denn die Dateiliste? DirectoryInfo.GetFiles() gibt doch bereits eine Liste mit den Dateiinfos zurück?
Außerdem wäre es ja wohl sinnvoller auf die mit GetFiles erhaltene Liste einfach einen Sortieralgorithmus anzuwenden. Dann wäre die Laufzeit bestimmt deutlich kürzer...
|
|
diego2k 
Hält's aus hier
Beiträge: 7
|
Verfasst: Fr 20.03.09 16:56
Das einlesen erfolgt an anderer Stelle im Programm, dass geht eigentlich recht flott.
Ich hab alle Datein in diesem List<string> dirnen und dieser gehört jetzt sortiert.
Bei 50000 Datein kommt er in einer Sec auf ca 3 durchläufe.
Der andere Algo. schaft um ein vielfaches mehr. Und das scheint an dem new FileInfo zu liegen. Das immer wieder neu erstellen verbraucht unglaublich viel leistung.
Ohne das new File info schafft man pro sec ca 1000 durchläufe.
Meine Frage ist wie mach ich das schneller ... bzw wie bekomm ich das ohne dem wörtchen new zum laufen?
|
|
bakachan
      
Beiträge: 503
Erhaltene Danke: 34
W7 (x64) Ultimate
C# / VB.NET (VS2010 Ultimate)
|
Verfasst: Fr 20.03.09 17:03
Sehe ich das richtig du hast die pfadangaben zu den dateien und willst die Dateinamen vergleichen? (in dem Bereich wo du die FileInfos anlegst)
Benutz doch einfach System.IO.Path.GetFileName(path); um aus den Pfadangaben die Dateinamen rauszukriegen. Das sollte auf jeden fall bedeutend schneller sein als immer wieder neue FileInfo-Objekte anzulegen.
|
|
diego2k 
Hält's aus hier
Beiträge: 7
|
Verfasst: Fr 20.03.09 17:49
Zitat: | Benutz doch einfach System.IO.Path.GetFileName(path); |
Danke, das is bis jetzt die schnellste Methode .. sie kommt ca auf 22 durchläufe pro sec
mit Strings sind ca 11.
das direkte vergleichen ist aber immernoch um ein vielfaches schneller ...
schneller wäre:
ein 2. array anlegen wo nur die namen drinnen stehen, diese dann direkt vergleichen.
nur wie kann ich dann den pfad wieder zuordnen 
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 20.03.09 18:41
Du hast immer noch nicht geantwortet woher die Dateiliste kommt? Schließlich gibt dir der Befehl zum Durchsuchen eines Verzeichnisses ja eigentlich die Liste der Dateiinfos direkt zurück, wie gesagt...
|
|
diego2k 
Hält's aus hier
Beiträge: 7
|
Verfasst: Fr 20.03.09 19:03
aus ner klasse ...
Ich kann die Files list nicht direkt nehmen einfach aus dem grund wie mein such alg. funktioniert:
->ich geben nen ordner an
->ordner wird durchsucht nach datein und weiteren ordnern
jetzt sind in der Files list von getFile die Datein des ersten Ordners
->jetzt wird der erste ordner der gefundenen ordner genommen und dieser nach Ordner udn Datein durchsucht
jetzt sind in der Files list von getFile die Datein des zweiten Ordners
usw usv
darum müssen die Datein aus der original Filesliste immer wieder in eine 2. überschrieben werden, diese zweite wird dann von verschiedenen weiteren Klassen mit ref übernommen.
jetzt siehts so aus:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| for (Int32 i = 0; i < couter; i++) { for (Int32 k = i+1; k < couter; k++) { if (Path.GetFileName(_data[i]) == Path.GetFileName(_data[k])) { _return.Add(_data[i]); } } } |
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 20.03.09 19:17
diego2k hat folgendes geschrieben : | aus ner klasse ...
Ich kann die Files list nicht direkt nehmen einfach aus dem grund wie mein such alg. funktioniert: |
Das ist aber kein Grund dafür, dass du die Dateiinformationen nicht verwendest, die du da (vermutlich) bereits bekommen hast.
|
|
diego2k 
Hält's aus hier
Beiträge: 7
|
Verfasst: Fr 20.03.09 19:37
Zitat: | Das ist aber kein Grund dafür, dass du die Dateiinformationen nicht verwendest, die du da (vermutlich) bereits bekommen hast. |
Doch, die Liste ist zu dem Zeitpunkt ja noch nicht vollständig.
Außerdem scheint er mir mit Path.GetFileName nur den String umzuschnippseln und nicht die infos noch mal neu zu laden.
Und bei der bereits vorhandenen Liste von GetFiles tut er, nehm ich mal an, auch nichts anderes als den String umzuschneiden, mal davpn abgesehen das ich mit der liste nix anfangen kann.
Und das einlesen der Datein zähl ich nicht zur Verarbeitungszeit dazu, die Liste wird händisch Eingelesen und zu nem sql query umformatiert. Die Liste kann dann durchsucht werden, um Duplikate zu finden. Und um genau das geht es mir jetzt, das schnelle aufspüren von Duplikaten.
Oder was meinst du jetzt genau?
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 20.03.09 21:16
Um GetFileName mit dem Dictionary-Ansatz zu verknüpfen, brauchst du einen IEqualityComparer:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| public class FileNameComparer : IEqualityComparer<string> { public bool Equals(string x, string y) { return Path.GetFileName(x) == Path.GetFileName(y); }
public int GetHashCode(string obj) { return Path.GetFileName(obj).GetHashCode(); } } |
Übergib eine Instanz dieser Klasse dem Dic-Konstruktor, dann sollte ContainsKey auch auf gleichnamige Dateien in verschiedenen Ordnern anschlagen.
PS: Ab 3.5 kann statt einem Dictionary<T, TDontNeedNoValue> einfach ein HashSet<T> verwendet werden.
_________________ >λ=
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 20.03.09 21:49
Ich meinte das so. Wobei sich für die Duplikate Khas Ansatz ja gut eignet. Aber ich poste das mal trotzdem was das Auslesen der Dateiliste direkt inkl. Dateiinfos angeht. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| public List<System.IO.FileInfo> GetFileList(System.IO.DirectoryInfo RootFolder, Boolean IncSubfolders) { List<System.IO.FileInfo> FileList = new List<System.IO.FileInfo>(); try { FileList.AddRange(RootFolder.GetFiles()); } catch {}
if (IncSubfolders) { try { System.IO.DirectoryInfo[] Folders = RootFolder.GetDirectories(); for (int i = 0; i < Folders.Length; i++) FileList.AddRange(GetFileList(Folders[i], IncSubfolders)); } catch { } } return FileList; }
private static int CompareFileInfosByName(System.IO.FileInfo a, System.IO.FileInfo b) { return String.Compare(a.Name, b.Name); }
private void button1_Click(object sender, EventArgs e) { List<System.IO.FileInfo> MyFileList = GetFileList( new System.IO.DirectoryInfo(textBox1.Text), true); MyFileList.Sort(CompareFileInfosByName); foreach (System.IO.FileInfo a in MyFileList) listBox1.Items.Add(a.FullName); } | Das Sortieren dauerte bei mir bei 70.000 Dateien nicht einmal eine Sekunde.
Danach sind Dateien mit gleichen Dateinamen direkt hintereinander in der Liste.
Ich überlege gerade wie Khas Ansatz hier am besten benutzt werden kann. Ich glaube dafür müsste man die Dateien dann trotzdem noch einmal durchgehen.
|
|
diego2k 
Hält's aus hier
Beiträge: 7
|
Verfasst: Sa 21.03.09 19:11
Danke für die hilfe.
habs so gemacht, damit hab ich in sec. schnell alle doppel- 3fach- usw Gänger von Datein:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| _data.Sort(CompareFileName);
for (Int32 i = 0; i < couter-1;i++ ) { if (Path.GetFileName(_data[i]) == Path.GetFileName(_data[i + 1])) { _return.Add(_data[i+1]); } }
private static int CompareFileName(string a, string b) { return String.Compare(Path.GetFileName(a), Path.GetFileName(b)); } |
Warum ist der Sortalgo. von c# um ein vielfaches schneller als ein normaler Bubblsort?
Und an der Stelle muss ich mich gleich wieder über die Vista Suche aufregen, die nicht funktioniert ...
Warum findet er mir Datein nicht die ich mit freiem Auge in nem Ordner finde, trotz indizierung und
Hacken bei "Nicht indizierte und Systemdatein einbeziehen" 
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 21.03.09 19:23
diego2k hat folgendes geschrieben : | Warum ist der Sortalgo. von c# um ein vielfaches schneller als ein normaler Bubblsort? |
Weil BubbleSort praktisch der langsamste Algorithmus ist, den man sich denken kann. Der taugt eigentlich fast nur zu Lehrzwecken um grundsätzlich an das Thema Sortieralgorithmen heranzuführen, aber nicht zum praktischen Einsatz.
Denn da gehst du ja x Mal die selben Einträge durch. Anders ist das bei QuickSort, das einen extrem viel geringeren Aufwand hat. Nicht ganz so gut ist QuickSort nur bei bereits (fast) fertig sortierten Listen, aber auch da natürlich besser als BubbleSort.
Schau dir einfach mal die Artikel und Animationen zu dem Thema an:
de.wikipedia.org/wiki/Quicksort
de.wikipedia.org/wiki/Bubblesort
|
|
diego2k 
Hält's aus hier
Beiträge: 7
|
Verfasst: Sa 21.03.09 19:56
thx werd ich gleich mal testen
|
|