Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

représentation arborescente de données

8 réponses
Avatar
Kevin Denis
Bonjour,

je cherche à trouver le meilleure moyen de stocker des données arborescentes.
Un cas typique d'utilisation est un filesystem (unix pour l'exemple).
Il y a une racine / contenant des dossiers et des fichiers.
Certains dossiers, /usr /home /lib, peuvent contenir des dossiers et des
fichiers, etc...

Le but est d'obtenir la somme totale de fichier et dossiers a chaque
étage et de faire plusieurs manipulations ensuite sur ces données
(entre autre pouvoir faire un graphe avec graphviz simplement)

J'ai d'imposé en entrée un fichier plat contenant une arborescence:
/
/home
/home/kevin
/home/kevin/prog.py
/usr
/usr/bin
etc...

Pour le premier niveau, pas de problèmes, je peux faire un dictionnaire:
root = {}
for dir in list:
if root.has_key(dir):
root[dir]=root[dir]+1
else:
root[dir]=1
et root contient la somme des fichiers et dossiers, et ça se processe
ensuite très facilement.

Mais pour le second niveau (et les suivants), j'ai du mal à trouver
une bonne méthode.

Avez vous une idée?

Merci
--
Kevin

8 réponses

Avatar
Tanguy Ortolo
Kevin Denis, 2013-09-18 21:28+0200:
je cherche à trouver le meilleure moyen de stocker des données arborescentes.
Un cas typique d'utilisation est un filesystem (unix pour l'exemple).
Il y a une racine / contenant des dossiers et des fichiers.
Certains dossiers, /usr /home /lib, peuvent contenir des dossiers et des
fichiers, etc...



Idéalement, il faudrait créer des classes spécifiques, mais d'une façon
générale la structure appropriée me semble être un dictionnaire par
répertoire, avec comme clefs les noms des fichiers, et comme valeurs des
dictionnaires pour les sous-répertoires, et ce que vous voulez pour les
fichiers réguliers.

Allez, on y va avec des classes dédiées :

class Directory:
def __init__(self, files=None):
if files:
self.files = files
else:
self.files = {}

class File:
pass

class Link:
def __init__(self, target):
self.target = target

class Socket:
pass

class Fifo:
pass

class Blockdev:
def __init__(self, minor, major):
self.minor = minor
self.major = major

class Chardev
def __init__(self, minor, major):
self.minor = minor
self.major = major

Les liens physiques multiples ne sont pas un type particulier, et
pourrons être pris en charge par références multiples aux mêmes objets.

Le but est d'obtenir la somme totale de fichier et dossiers a chaque
étage et de faire plusieurs manipulations ensuite sur ces données
(entre autre pouvoir faire un graphe avec graphviz simplement)

J'ai d'imposé en entrée un fichier plat contenant une arborescence:
/
/home
/home/kevin
/home/kevin/prog.py
/usr
/usr/bin
etc...



Allons y alors. Faute d'information sur les types de fichiers, il va
falloir supposer que tout est fichier régulier, et corriger en en
changeant en répertoires lorsqu'on détecte des fichiers dessous. Ce
serait plus simple et surtout plus juste si on avait le type de chaque
fichier, mais bon…

root = Directory()
for line in sys.stdin:
line
components = line.rstrip().split(os.path.sep)
// Consider all components except the last one: they are
// directories
parent = root
for component in components[:-1]:
if not component in parent.files
or not isinstance(parent.files[component], Directory):
parent.files[component] = Directory()
parent = parent.files[component]
// The last component is supposed to be a regular file, though
// it may be replaced by a directory if it is found to contain
// files.
parent.files[components[-1] = File()

Bon, souvenons-nous du but : obtenir un dictionnaire donnant le nombre
de fichiers dans chaque répertoire. Il va falloir récurer avec un
accumulateur je pense.

def filecount(dirname, directory, count=[]):
count[dirname] = len(directory.files)
for filename in directory.files:
file = directory.files[filename]
// Add file counts of each subdirectory
if isinstance(file, Directory):
filecount('%s%s%s' % (dirname, os.path.sep, filename),
file, count)

count = filecount('/', root)


(code non testé)

--
. o .
. . o Tanguy
o o o
Avatar
Pierre Maurette
Kevin Denis :
Bonjour,

je cherche à trouver le meilleure moyen de stocker des données arborescentes.
Un cas typique d'utilisation est un filesystem (unix pour l'exemple).
Il y a une racine / contenant des dossiers et des fichiers.
Certains dossiers, /usr /home /lib, peuvent contenir des dossiers et des
fichiers, etc...

Le but est d'obtenir la somme totale de fichier et dossiers a chaque
étage et de faire plusieurs manipulations ensuite sur ces données
(entre autre pouvoir faire un graphe avec graphviz simplement)

J'ai d'imposé en entrée un fichier plat contenant une arborescence:
/
/home
/home/kevin
/home/kevin/prog.py
/usr
/usr/bin
etc...

Pour le premier niveau, pas de problèmes, je peux faire un dictionnaire:
root = {}
for dir in list:
if root.has_key(dir):
root[dir]=root[dir]+1
else:
root[dir]=1
et root contient la somme des fichiers et dossiers, et ça se processe
ensuite très facilement.

Mais pour le second niveau (et les suivants), j'ai du mal à trouver
une bonne méthode.

Avez vous une idée?



Je ne suis pas certain de bien comprendre votre demande. S'il s'agit du
système de fichiers, il me semble que os.walk() conviendrait:

(remplacer dans le texte et le code "zorglub" par "files", "dirs" ou
"files + dirs")

Pour compter les /zorglub/s sous chaque niveau:
results = {}
for root, dirs, files in os.walk(ROOTPATH, topdownúlse):
results[root] = sum([results[os.path.join(root, d)] for d in dirs])
+ len(zorglub)

Pour lister les noms courts des /zorglub/s sous chaque niveau:
results = {}
for root, dirs, files in os.walk(ROOTPATH, topdownúlse):
results[root] = zorglub + sum([results[os.path.join(root, d)] for d
in dirs], [])

Pour lister les chemins complets des /zorglub/s sous chaque niveau:
results = {}
for root, dirs, files in os.walk(ROOTPATH, topdownúlse):
zorglub = files + dirs
results[root] = [os.path.join(root, f) for f in zorglub] +
sum([results[os.path.join(root, d)] for d in dirs], [])

--
Pierre Maurette
Avatar
Pierre Maurette
(supersedes )

Kevin Denis :
Bonjour,

je cherche à trouver le meilleure moyen de stocker des données
arborescentes.
Un cas typique d'utilisation est un filesystem (unix pour l'exemple).
Il y a une racine / contenant des dossiers et des fichiers.
Certains dossiers, /usr /home /lib, peuvent contenir des dossiers et des
fichiers, etc...

Le but est d'obtenir la somme totale de fichier et dossiers a chaque
étage et de faire plusieurs manipulations ensuite sur ces données
(entre autre pouvoir faire un graphe avec graphviz simplement)

J'ai d'imposé en entrée un fichier plat contenant une arborescence:
/
/home
/home/kevin
/home/kevin/prog.py
/usr
/usr/bin
etc...

Pour le premier niveau, pas de problèmes, je peux faire un dictionnaire:
root = {}
for dir in list:
if root.has_key(dir):
root[dir]=root[dir]+1
else:
root[dir]=1
et root contient la somme des fichiers et dossiers, et ça se processe
ensuite très facilement.

Mais pour le second niveau (et les suivants), j'ai du mal à trouver une
bonne méthode.

Avez vous une idée?



Je ne suis pas certain de bien comprendre votre demande. S'il s'agit du
système de fichiers, il me semble que os.walk() conviendrait:

(remplacer dans le texte et le code "zorglub" par "files", "dirs" ou
"files + dirs")

Pour compter les /zorglub/s sous chaque niveau:
results = {}
for root, dirs, files in os.walk(ROOTPATH, topdownúlse):
results[root] = sum([results[os.path.join(root, d)] for d in dirs])
+ len(zorglub)

Pour lister les noms courts des /zorglub/s sous chaque niveau:
results = {}
for root, dirs, files in os.walk(ROOTPATH, topdownúlse):
results[root] = zorglub + sum([results[os.path.join(root, d)] for d
in dirs], [])

Pour lister les chemins complets des /zorglub/s sous chaque niveau:
results = {}
for root, dirs, files in os.walk(ROOTPATH, topdownúlse):
results[root] = [os.path.join(root, f) for f in zorglub] +
sum([results[os.path.join(root, d)] for d in dirs], [])

--
Pierre Maurette
Avatar
Tanguy Ortolo
Pierre Maurette, 2013-09-19 09:23+0200:
(remplacer dans le texte et le code "zorglub" par "files", "dirs" ou
"files + dirs")



Attention, comme je l'ai indiqué de façon plus ou moins explicite dans
mon message précédent, tous les fichiers ne sont pas des fichiers
réguliers ou des répertoires, il y a aussi des lien symboliques, des
tubes nommés ou FIFO, des sockets Unix, des périphériques bloc et des
périphériques caractère.

--
. o .
. . o Tanguy
o o o
Avatar
Kevin Denis
Le 19-09-2013, Pierre Maurette a écrit :
je cherche à trouver le meilleure moyen de stocker des données
arborescentes.
J'ai d'imposé en entrée un fichier plat contenant une arborescence:
/
/home
/home/kevin
/home/kevin/prog.py
/usr
/usr/bin
etc...

Pour le premier niveau, pas de problèmes, je peux faire un dictionnaire:
root = {}
for dir in list:
if root.has_key(dir):
root[dir]=root[dir]+1
else:
root[dir]=1
et root contient la somme des fichiers et dossiers, et ça se processe
ensuite très facilement.

Mais pour le second niveau (et les suivants), j'ai du mal à trouver une
bonne méthode.

Avez vous une idée?



Je ne suis pas certain de bien comprendre votre demande. S'il s'agit du
système de fichiers, il me semble que os.walk() conviendrait:



Je vais essayer d'être plus clair.
Le système de fichier n'est qu'un exemple de données arborescentes.
J'aurai pu avoir:
.
.animaux
.animaux.plume
.animaux.plume.oiseau
.animaux.plume.oiseau.pélican
.animaux.carapace
.animaux.carapace.tortue

etc..

Et le but est de manipuler facilement les données à l'intérieur:
-par exemple connaitre la somme des oiseaux. Ou de connaitre la chaine
la plus longue, ou de l'exporter dans autre chose, etc..

J'ai un cas d'usage précis ou je voudrais exporter tout ça dans
un graphe neato (graphviz) pour obtenir une représentation graphique
de ce fichier plat.
--
Kevin
Avatar
Tanguy Ortolo
Kevin Denis, 2013-09-19 10:43+0200:
.animaux
.animaux.plume
.animaux.plume.oiseau
.animaux.plume.oiseau.pélican
.animaux.carapace
.animaux.carapace.tortue



Allons-y pour un arbre sans sémantique particulière.

class Node:
def __init__(self, children=None):
if children:
self.children = children
else
self.children = {}

root = Node()
for line in sys.stdin:
elements = line.rstrip().split('.')
current = root
for element in elements:
# Create elements that are not already in the root tree
if not element in current.children:
current.children[element] = Node()
# Update current pointer to the current node
current = current.children[element]

Après, tu fais toutes les stats que tu veux avec l'arbre root, sachant
que tu vas probablement avoir besoin de définir des fonctions récursives
avec accumulateur. D'ailleurs, un avantage de Python est qu'il est
inutile de définir des fonctions auxiliaires avec accumulateur puis des
fonctions principales appelant ces auxiliaires avec un accumulateur
vide, puisqu'on peut tout simplement définir une fonction avec un
accumulateur optionnel, vide par défaut.

--
. o .
. . o Tanguy
o o o
Avatar
pbiopy
Bonjour,

Pourquoi ne pas traiter les donnés sous un format de type
arborescence comme "json" ou "xml". Après vous pourrez utiliser les
lib de python pour extraire les informations et les utiliser.

On 19 Sep 2013 12:55:22 GMT, Tanguy Ortolo wrote:
Kevin Denis, 2013-09-19 10:43+0200:
> .animaux
> .animaux.plume
> .animaux.plume.oiseau
> .animaux.plume.oiseau.pélican
> .animaux.carapace
> .animaux.carapace.tortue


Allons-y pour un arbre sans sémantique particulière.


class Node:
def __init__(self, children=None):
if children:
self.children = children
else
self.children = {}


root = Node()
for line in sys.stdin:
elements = line.rstrip().split('.')
current = root
for element in elements:
# Create elements that are not already in the root tree
if not element in current.children:
current.children[element] = Node()
# Update current pointer to the current node
current = current.children[element]


Après, tu fais toutes les stats que tu veux avec l'arbre root,


sachant
que tu vas probablement avoir besoin de définir des fonctions


récursives
avec accumulateur. D'ailleurs, un avantage de Python est qu'il est
inutile de définir des fonctions auxiliaires avec accumulateur puis


des
fonctions principales appelant ces auxiliaires avec un accumulateur
vide, puisqu'on peut tout simplement définir une fonction avec un
accumulateur optionnel, vide par défaut.


--
. o .
. . o Tanguy
o o o



--
pbouige
Avatar
pbiopy
Bonjour,
Pourquoi pas un format type xml ou json pour faire une arborescence
de vos données ?

--
pbouige