преобразование древовидного списка в список с полным путем

Я пытаюсь использовать функцию file-system-tree из https://www.gnu.org/software/guile/manual/html_node/File-Tree-Walk.html#File-Tree-Walk. В сочетании с remove-statиз ссылки это приводит к древовидной структуре списка, например. за

test/
├── dir1
├── dir2
│   ├── file2
│   └── file3
└── file1

мы получаем ("test" (("dir2" ("file2" "file3")) "dir1" "file1"))

Как преобразовать этот список в список всех полных путей? вот так ("test/" "test/file1" "test/dir2" "test/dir2/file3" "test/dir2/file2" "test/dir1")


person sciamano    schedule 01.11.2017    source источник
comment
Добро пожаловать в переполнение стека. Вы должны быть более конкретными. Что ты уже испробовал? Где ты застрял? Прочтите Как задать вопрос и исправьте свой вопрос.   -  person Johan    schedule 01.11.2017


Ответы (2)


Что нам нужно сделать, так это определить рекурсивную функцию, которая перебирает car из cdr заданного списка, добавляет car списка к элементам строки и вызывает себя в другом элементе списка, затем берет возвращенные элементы и добавляет car из списка на тех, тоже. Вот как это будет выглядеть в коде:

(define (tree->full-path-list tree)
  (flatten (append (list (car tree))
                   (map (lambda (x)
                          (if (list? x)
                              (map (lambda (y)
                                     (string-append (car tree) "/" y))
                                   (tree->full-path-list x))
                              (string-append (car tree) "/" x)))
                        (car (cdr tree))))))

Надеюсь, это поможет!

person Christopher Dumas    schedule 01.11.2017
comment
спасибо, это именно то, что я искал, но мне так и не удалось использовать карту-на-карте-на-рекурсии - person sciamano; 01.11.2017
comment
Рад это слышать, @sciamano! На самом деле, говоря о карте на карте, я бы предпочел найти способ избежать вложения двух очень похожих map. На самом деле, если кто-нибудь знает хороший способ устранить это, я бы очень хотел знать. - person Christopher Dumas; 01.11.2017
comment
@ChristopherDumas Может быть, взгляните на мой ответ, который вообще избегает map. - person uselpa; 03.11.2017

Я опаздываю на вечеринку, но я думаю, что это можно сделать гораздо проще (и, вероятно, быстрее), чем принятое решение, используя классический named-let:

(define (path-append part1 part2)
  ;; concatenate paths (lazy man's version)
  (if (non-empty-string? part1)
      (string-append part1 "/" part2)
      part2))

(define (f lst)
  (reverse 
   (let loop ((lst lst) (path "") (res null))
     (if (null? lst)
         res
         (let ((c (car lst)))
           (loop (cdr lst)
                 path
                 (if (list? c)
                     (loop c (car res) res) ; this recurses into sub-lists
                     (cons (path-append path c) res))))))))

Не идеально, но близко:

> (f '("test" (("dir2" ("file2" "file3")) "dir1" "file1")))
'("test" "test/dir2" "test/dir2/file2" "test/dir2/file3" "test/dir1" "test/file1")
person uselpa    schedule 02.11.2017