Marche/itération sur un imbriquée dictionnaire de profondeur arbitraire (le dictionnaire représente une arborescence de répertoires)
Je suis presque certain qu'il existe une solution simple à ce problème, mais j'ai passé des heures à lire et relire le même ensemble de résultats qui ne sont pas tout à fait répondre à mon problème.
Contexte de cette question (inclus pour la réalisation, mais n'hésitez pas à sauter cette)
C'est venu parce que je veux à un utilisateur d'être en mesure de sélectionner un groupe de fichiers dans un répertoire (et aussi les sous-répertoire), et, malheureusement, Tkinter, de la capacité par défaut pour la sélection de plusieurs fichiers dans une boîte de dialogue de fichier est cassé sur Windows 7 (http://bugs.python.org/issue8010).
Donc j'essaie de représenter une structure de répertoires par une méthode alternative (toujours en utilisant Tkinter): la construction d'un fac-similé de la structure de répertoire, fait de étiquetés et décalés des cases à cocher (organisés dans un arbre). Ainsi, un répertoire comme ceci:
\SomeRootDirectory
\foo.txt
\bar.txt
\Stories
\Horror
\scary.txt
\Trash
\notscary.txt
\Cyberpunk
\Poems
\doyoureadme.txt
va ressembler à quelque chose comme ceci (où # représente un checkbutton):
SomeRootDirectory
# foo.txt
# bar.txt
Stories
Horror
# scary.txt
Trash
# notscary.txt
Cyberpunk
Poems
# doyoureadme.txt
La construction du dictionnaire initial de la structure de répertoire est facile à l'aide d'un certain recette que j'ai trouvé à la ActiveState (voir ci-dessous), mais j'ai frappé un mur lorsque je tente d'effectuer une itération sur le bien imbriqués dictionnaire, je suis reparti avec. Et je pense que j'ai besoin pour effectuer une itération sur elle afin de remplir un Tkinter cadre avec une jolie maillées représentation de l'arbre. Alors j'espère charge dans les différents fichiers de texte sélectionné par l'utilisateur, par l'interprétation qui les cases étaient vraies ou fausses. Tout semble assez facile à l'exception de parcourir le dictionnaire sans la fixation de la profondeur.
En plus de termes abstraits
De faire de ces dictionnaires imbriqués, je suis en utilisant un ActiveState recette -- http://code.activestate.com/recipes/577879/. Il met en oeuvre des os.pied pour faire les dictionnaires comme ceci:
a={
'SomeRootDirectory': {
'foo.txt': None,
'bar.txt': None,
'Stories': {
'Horror': {
'horror.txt' : None,
'Trash' : {
'notscary.txt' : None,
},
},
'Cyberpunk' : None
},
'Poems' : {
'doyoureadme.txt' : None
}
}
}
Après le point, je suis perplexe. Je suis un débutant en Python au moment de la rédaction
Solution adaptée à partir de spicavigo réponse
#distinguish between directory and file
dirtab = "/==="
filetab = "|---"
Parents={ -1:"Root"}
def add_dir(level, parent, index, k):
print (dirtab*level)+k
def add_file(level, parent, index, k):
#Currently an empty folder gets passed to add_file; here's a quick treatment.
if "." in k:
print (filetab*level)+k
else:
print (dirtab*level)+k
def addemup(level=0, parent=-1, index=0, di={}):
for k in di:
index +=1
if di[k]:
Parents[index]=k
add_dir(level, parent, index, k)
addemup(level+1, index, index, di[k])
else:
add_file(level, parent, index, k)
addemup(di=a) #dictionary from above
Ce produit quelque chose qui je pense sera très facile de réviser dans un Tkinter représentation:
SomeRootDirectory
/===Poems
|--- | ---doyoureadme.txt
/===Stories
/===/===Horror
|--- | --- | ---rickscott.txt
/===/===/===Trash
|--- | --- | --- | ---notscary.txt
/===/===Cyberpunk
|---foo.txt
|---bar.txt
Grâce, cette communauté est incroyable.
OriginalL'auteur hangtwenty | 2011-10-12
Vous devez vous connecter pour publier un commentaire.
C'est un préliminaire du code. Aller à travers elle et dites-moi où vous confrontés à des problèmes.
OriginalL'auteur spicavigo
Voici une fonction qui imprime tous vos noms de fichier. Il passe par toutes les clés dans le dictionnaire, et si ils correspondent à des choses qui ne sont pas des dictionnaires (dans votre cas, le nom de fichier), nous imprimons le nom. Sinon, nous appelons la fonction sur le dictionnaire qui est mappé à.
Donc, ce code peut être modifié pour faire ce que vous voulez, mais c'est juste un exemple de comment vous pouvez éviter la fixation de la profondeur grâce à l'utilisation de la récursivité.
L'essentiel à comprendre est que chaque fois print_all_files est appelée, elle n'a aucune connaissance de la façon dont profondément dans l'arbre. Il semble juste les fichiers qui sont là, et imprime les noms. Si il y directores, il fonctionne sur.
OriginalL'auteur oadams
Je réalise que c'est une vieille question, mais je viens de regarder pour une solution simple, propre façon de marcher imbriquée dicts et c'est la chose la plus proche que mon peu de recherche a trouvé. oadams réponse n'est pas assez utile si vous voulez plus que juste les noms de fichiers et spicavigo la réponse semble compliqué.
J'ai fini juste de lancer mon propre que des actes semblables à comment os.pied traite répertoires, sauf qu'il retourne toutes les clés/valeur de l'information.
Il retourne un itérateur et pour chaque répertoire dans l'arborescence de imbriquée dicts, renvoie l'itérateur (chemin, sous-dicts, valeurs) où:
Voici le code que j'ai utilisé pour le tester, si elle a un couple d'autres indépendants (mais joli) des choses:
La sortie ressemble à ceci:
OriginalL'auteur bj0
OriginalL'auteur wagner
Vous pouvez marcher un imbriquée dictionnaire en utilisant la récursivité
Espère que cela aide 🙂
OriginalL'auteur FintanH