Nur die höchsten Elemente einer Verzeichnisstruktur erhalten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Hallo, ich bin mal wieder auf der Suche nach einer Funktion. Bin leider selbst nicht fündig geworden, glaube aber trotzdem noch dass es sowas ähnliches geben müsste. Bin garantiert nicht der erste der sowas braucht. Bevor ich mir also nen "Kopf" mache und sie selbst erstelle... fragen kostet ja nichts.

Ich hätte gerne folgendes:

Code: Alles auswählen

>>> filter_highest([r'a\b\c', r'a\b', r'b\c\d', 'b', r'c\e'])
['a\\b', 'b', 'c\\e']
Gibts da was ähnliches? Standardlib? Snippet? Oder hat jemand ein "Stichwort" mit dem Google u. Co etwas passendes finden könnte?
BlackJack

@Gremlin: Also es sieht so aus, als wenn Du die Pfade erst nach dem ersten/obersten Element gruppieren möchtest und danach den „longest common prefix” in jeder Gruppe suchst.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:@Gremlin: Also es sieht so aus, als wenn Du die Pfade erst nach dem ersten/obersten Element gruppieren möchtest und danach den „longest common prefix” in jeder Gruppe suchst.
Für zweiteres kann man dann os.path.commonprefix einsetzen
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Danke BlackJack. Ist immer schöner zu wissen wovon man redet. :mrgreen:

Allerdings ist mir nach einiger Zeit doch eine Idee gekommen wie ich das relativ simpel lösen könnte. Gefällt mir auch von der Geschwindigkeit her recht gut. Nur sollte man nicht absolute und relative Pfade vermischen. :roll:

os.path.commonprefix hab ich auch mal probiert, aber auch da muss ich erst (wie erwähnt) die Pfade im voraus gruppieren, somit hat das ja auch keinen besonderen Vorteil gegenüber meinem Werk, oder?

Code: Alles auswählen

import os
import timeit


def filter_root_directories(dirs):
    filtered_dirs = []
    while dirs:
        path = dirs.pop(0)
        search_path = path
        if not search_path.endswith(os.sep):
            search_path = ''.join((search_path, os.sep))
        add = True
        for cmp_path in dirs[:]:
            if cmp_path.startswith(search_path):
                dirs.remove(cmp_path)
            else:
                if not cmp_path.endswith(os.sep):
                    cmp_path = ''.join((cmp_path, os.sep))
                if search_path.startswith(cmp_path):
                    add = False
                    break
        if add:
            filtered_dirs.append(path)
    return filtered_dirs


paths = ['eins\\zwei\\drei\\vier', 'eins\\drei\\zwei', 'zwei',
         'zwei\\drei', 'eins\\drei', 'eins\\zwei\\drei', 'sieben']

print filter_root_directories(paths[:])
print timeit.timeit('filter_root_directories(paths[:])',
                    'from __main__ import filter_root_directories, paths',
                    number=10)
BlackJack

@Gremlin: Es wäre wahrscheinlich weniger kryptisch und die Laufzeit sieht bei Dir auch nicht gerade schön aus. Das ist ja mindestens quadratisch.

Edit:

Code: Alles auswählen

import os
from itertools import groupby


def filter_root_directories(paths):
    
    def get_first_path_element(path):
        return path.split(os.path.sep, 1)[0]
    
    return [
        os.path.commonprefix(list(path_iter))
        for _, path_iter in groupby(sorted(paths), get_first_path_element)
    ]
Antworten