MRU-Struktur mit fester Anzahl von Elementen, die sich automatisch an LINQ-Abfragen anpasstC#

Ein Treffpunkt für C#-Programmierer
Anonymous
 MRU-Struktur mit fester Anzahl von Elementen, die sich automatisch an LINQ-Abfragen anpasst

Post by Anonymous »

Ich habe einen Ordner, der eine große Anzahl von Dateien in vielen Unterordnern enthält, und ich möchte die Dateien auswählen, deren Namen mit einem der angegebenen Muster (regulären Ausdrücke) übereinstimmen. Meine regulären Ausdrücke sind komplex, ich kann sie nicht in einem einzigen kombinieren. Mein Problem ist, dass die Zuordnung aller Dateinamen zu allen Mustern Zeit braucht und ich die Dinge beschleunigen möchte. Derzeit sieht mein Code so aus:

Code: Select all

Regex[] regexes = [new(@"^[a-f]+$"), new(@"^[g-l]+$"), new(@"^[m-r]+$"), new(@"^[s-x]+$")];
string[] matchedPaths = Directory
.EnumerateFiles(@"C:\Files", "*.*", SearchOption.AllDirectories)
.Where(path =>
{
string name = Path.GetFileNameWithoutExtension(path);
return regexes.Any(regex => regex.IsMatch(name));
})
.ToArray();
Die tatsächlichen Muster sind viel komplexer, ich zeige nur ein Beispiel.
Meine Idee, dieses Problem zu lösen, beruht auf der Tatsache, dass jeder Ordner meist Dateien enthält, die einem bestimmten Muster entsprechen. Wenn ich also mit dem Abgleich mit dem Muster beginne, das mit der vorherigen Datei übereinstimmt, ist die Wahrscheinlichkeit groß, dass es auch mit demselben Muster abgeglichen wird (oder mit keinem Muster übereinstimmt). Anstatt meine regulären Ausdrücke in einem Standardarray zu platzieren, denke ich darüber nach, sie in eine MRU-Struktur (Most Latest Used) einzufügen, die ihren Inhalt nach jedem erfolgreichen Any LINQ-Vorgang aktiv neu anordnet. Wenn es mir gelingt, diese Struktur zu implementieren, muss ich in meinem Code nur die Definition der regulären Ausdrücke ändern:

Code: Select all

MruArray regexes = new(new(@"^[a-f]+$"), new(@"^[g-l]+$"), ...
Die API dieser Struktur könnte so etwas Einfaches sein:

Code: Select all

class MruArray : IEnumerable
{
public MruArray(params T[] items);
public IEnumerator GetEnumerator();
}
...und sollte sich wie folgt verhalten:

Code: Select all

MruArray mru = new(1, 2, 3, 4, 5, 6, 7, 8);
_ = mru.Any(x => x == 5);
Console.WriteLine(String.Join(", ", mru));
_ = mru.Any(x => x == 3);
Console.WriteLine(String.Join(", ", mru));
_ = mru.Any(x => x == 8);
Console.WriteLine(String.Join(", ", mru));
Ausgabe:

Code: Select all

5, 1, 2, 3, 4, 6, 7, 8
3, 5, 1, 2, 4, 6, 7, 8
8, 3, 5, 1, 2, 4, 6, 7
  • Wenn Any eine Übereinstimmung in der Sequenz findet, sollte das letzte aufgezählte Element an erster Stelle stehen.
  • Wenn Any die gesamte Sequenz auflistet, ohne eine Übereinstimmung zu finden, sollte die Sequenz unverändert bleiben.
Wie kann ich diese Struktur implementieren?
Thread-Sicherheit ist unerwünscht. Die Struktur sollte für Multithreading ohne Synchronisierung nicht sicher sein.
Hinweis: Der Schwerpunkt der Frage liegt auf der Implementierung der MRU-Datenstruktur, nicht auf anderen Ideen zur Beschleunigung der Suche im Ordner.
Bearbeiten: Ich habe oben eine vereinfachte Version meines Problems vorgestellt. In Wirklichkeit bin ich nicht nur an den Dateien interessiert, die dem Muster entsprechen. Ich interessiere mich für Unterausdrücke innerhalb der Muster und gruppiere dann die Dateien basierend auf diesen Unterausdrücken. Mein eigentlicher Code sieht also eher so aus:

Code: Select all

KeyValuePair[] groups = Directory
.EnumerateFiles(@"C:\Files", "*.*", SearchOption.AllDirectories)
.Select(p => Path.GetFileNameWithoutExtension(p))
.Select(n => regexes.Select(r => r.Match(n)).FirstOrDefault(m => m.Success))
.Where(m => m is not null)
.Select(m => m.Groups["Name"].Value)
.CountBy(x => x)
.OrderBy(p => p.Key, StringComparer.OrdinalIgnoreCase)
.ToArray();
Diese Details sollten nicht vom Fokus der Frage ablenken, nämlich der angeforderten MRU-Datenstrukturimplementierung.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post