Aller au contenu

Challenge récursive 2


(gile)

Messages recommandés

Merci, Gile, je commence à comprendre mon erreur,

je vais refaire des essais en le plaçant différemment et peux etre 2 fois comme le cddr.

Car si cette dernière fonctionne, c'est pour moi une pirouette (suis habitué :(rires forts): ).

Dans le sens que c'est grâce au placement de l’élément dans la liste, mais pas grâce à son contenu.

Si on ne voulais pas un dossier contenant temp par exemple, la on est pas bien...

Je suis loin d’être un perfectionniste, mais ce genre de challenge sont de bon prétexte didactique.

A plus tard pour une nouvelle version. (si je m'en sort, vais pas passé l'été la dessus non plus...)

Lien vers le commentaire
Partager sur d’autres sites

Bonjour à tous

 

Ma version

(defun rch_che(rep)
 (cons rep (mapcar '(lambda(x)
    	      (rch_che (if (= (substr rep (strlen rep) 1) "\\")
			 (strcat rep x)
			 (strcat rep "\\" x)
		       )
	      )
	    )
	    (if (= (substr rep (strlen rep) 1) "\\")
	      (vl-directory-files rep "*.*" -1)
	      (cddr (vl-directory-files rep "*.*" -1))
	    )
    )
 )
)

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Je remet un code publié en 2006: comment trouver un fichier depuis un lisp

 

L'optimisation est peut être possible..., mais là j'ai pas trop le temps!

 

(defun extract_folder (lst_fold / l_dir l)
 (setq l_dir '())
 (foreach n lst_fold
   (setq l (vl-directory-files n nil -1))
   (if (eq (car l) ".")
     (setq l (cddr l))
   )
   (cond
     (l
       (setq l_dir
         (append
           (mapcar
             '(lambda (x)
               (strcat n x "/")
             )
             l
           )
           l_dir
         )
       )
     )
   )
 )
 l_dir
)
(defun c:where_file ( / disk_unit folder_name file2find folder_list)
 (setq
   disk_unit (getstring T "\nUnité de disque? : ")
   folder_name (strcat disk_unit (vl-string-translate "\\" "/" (getstring T "\nDémarrer du dossier? : ")))
   file2find (getstring T "\nFichier à trouver? : ")
   folder_list (list folder_name)
 )
 (textscr)
 (if (vl-directory-files folder_name file2find 1)
   (princ (strcat "\nFichier " file2find " trouvé dans le dossier " (strcase (vl-string-translate "/" "\\" folder_name))))
 )
 (while (setq folder_list (extract_folder folder_list))
   (foreach n folder_list
     (if (vl-directory-files n file2find 1)
       (princ (strcat "\nFichier " file2find " trouvé dans le dossier " (strcase (vl-string-translate "/" "\\" n))))
     )
   )
 )
 (prin1)
)

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Lien vers le commentaire
Partager sur d’autres sites

@bonucad, (très) intéressant, mais ça ne répond pas précisément à la demande.

 

@Patrick_35, il me semble que le test :

if (= (substr rep (strlen rep) 1) "\\") ...)

n'est indispensable qu'au premier appel.

Ceci dit, ta réponse répond parfaitement à la question reformulée réponse #10, il ne reste plus maintenant qu'à "aplatir" la liste pour répondre à la demande originale.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Salut

 

Oui, mais avec une récursive, difficile de faire autrement, à moins de créer une fonction comme ma 1ere version.

J'ai pensé remettre la liste à plat, et cela revient à la demande initiale.

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Je vais donner ma réponse.

 

Afin de ne pas alourdir le code, on considère que le nom de dossier passé comme argument à la fonction récursive ne se termine pas par le séparateur de dossier (vl-string-right-trim "\\" "C:\\Temp\\dossier racine\\").

 

Pour répondre à la question reformulée réponse #10, je dois faire une fonction qui retourne une liste qui décrit l'arborescence.

Dans cette liste, un dossier est représenté par une liste contenant le chemin du dossier et les sous-dossiers qu'il contient représentés de la même façon (algorithme récursif).

Ma réponse est semblable à celle de Patrick_35 (l'utilisation de vl-remove plutôt que cddr permet de traiter aussi les lecteurs).

 

(defun GetFolderTree (dir)
 (cons dir
       (mapcar
         '(lambda (x)
            (GetFolderTree (strcat dir "\\" x))
          )
         (vl-remove "."
                    (vl-remove ".."
                               (vl-directory-files dir nil -1)
                    )
         )
       )
 )
)

 

(GetFolderTree (vl-string-right-trim "\\" "C:\\Temp\\dossier racine\\")) renvoie :

("C:\\Temp\\dossier racine"
 ("C:\\Temp\\dossier racine\\Dossier 1"
   ("C:\\Temp\\dossier racine\\Dossier 1\\Sous dossier 1.1"
     ("C:\\Temp\\dossier racine\\Dossier 1\\Sous dossier 1.1\\Bidule")
     ("C:\\Temp\\dossier racine\\Dossier 1\\Sous dossier 1.1\\Truc"
       ("C:\\Temp\\dossier racine\\Dossier 1\\Sous dossier 1.1\\Truc\\Machin")
     )
   )
   ("C:\\Temp\\dossier racine\\Dossier 1\\Sous dossier 1.2")
 )
 ("C:\\Temp\\dossier racine\\Dossier 2"
   ("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.1")
   ("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.2")
 )
)

 

Pour répondre à la question originale et obtenir une simple liste de chemins, il faut "aplatir" cette liste de sous-liste.

Si on prend un branche simple :

  ("C:\\Temp\\dossier racine\\Dossier 2"
   ("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.1")
   ("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.2")
 )

elle a été obtenue par l'évaluation de :

(cons "C:\\Temp\\dossier racine\\Dossier 2"
     (list
       '("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.1")
       '("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.2")
     )
)

où (list ...) est le résultat du (mapcar ...)

Pour "aplatir" cette liste, il suffit d'appliquer append à la liste :

(cons "C:\\Temp\\dossier racine\\Dossier 2"
     (apply 'append
            (list
              '("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.1")
              '("C:\\Temp\\dossier racine\\Dossier 2\\Sous dossier 2.2")
            )
     )
)

Il suffit donc d'ajouter (apply 'append ...) dans la fonction GetFolderTree pour aplatir récursivement mon arbre :

(defun GetFolders (dir)
 (cons dir
       (apply
         'append
         (mapcar
           '(lambda (x)
              (GetFolders (strcat dir "\\" x))
            )
           (vl-remove "."
                      (vl-remove ".."
                                 (vl-directory-files dir nil -1)
                      )
           )
         )
       )
 )
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

ho punaise... j'ai du boulot... pour mettre en application ces figures de styles dans mon projet.

Quand on a les mains dans le cambouis, on a pas ce genre de réflexe spontanément. (à mon niveau ). Encore un merci à (gile) pour la leçon de choses récursives

 

Du coup sans me changer fondamentalement l'algo, il faut que je révise ces apply, mapcar et compagnie. Je multiplie les boucles imbriquées il y a moyen de les compacter pas mal.

 

 

 

 

 

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...

Bonjour,

 

Très rapidement, juste pour le plaisir de proposer une autre écriture récursive sur la façon de parcourir une arborescence, si on ne veut pas passer par des solutions écrites avec mapcar (très en retard sur le challenge, des versions sont déjà proposé par Patrick_35 & (gile)).

 

 

(defun GetFolders (dir / directory files)
 (defun directory (dir)
   (cons dir (files (vl-remove "." (vl-remove ".." (vl-directory-files dir nil -1)))))
 )
 (defun files (rep)
   (if rep
     (append (directory (strcat dir "\\" (car rep))) (files (cdr rep)))
   )
 )
 (directory dir)
)

 

 

A+ Bruno

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité