Loop к структуре файловой системы в моем объекте, чтобы получить все файлы

Я получаю Javascript Object с моего сервера, который изображает файловую систему. Теперь я хочу получить путь от всех файлов в системе, например. конечные точки дерева.

Пример структуры файла:

└── pages
    └── services
        └── project            
            │── headline
            │── test
            │   └── text
            │   └── picture 
            │── text

Считываемый JSON:

{
"path":"/pages/services/project",
"is_dir":true,
"children":[
  {
     "path":"/pages/services/project/headline",
     "is_dir":false,
     "children":[

     ]
  },
  {
     "path":"/pages/services/project/text",
     "is_dir":false,
     "children":[

     ]
  },
  {
     "path":"/pages/services/project/test/",
     "is_dir":true,
     "children":[
        {
           "path":"/pages/services/project/test/text",
           "is_dir":false,
           "children":[

           ]
        },
        {
           "path":"/pages/services/project/test/picture",
           "is_dir":false,
           "children":[

           ]
        }
     ]
  }

]    }

Ожидаемый результат:

/pages/services/project/headline
/pages/services/project/text
/pages/services/project/test/text
/pages/services/project/test/picture

Я немного поиграл с рекурсией и сделал тупую функцию, которая работает, когда в директории есть только один ребенок. Моя проблема в том, что я не могу понять, как обращаться с большим количеством детей. Есть ли способ перебора каждого ребенка?

Здесь мой код:

var json = {"path":"/pages/services/project", "is_dir":true, "children":[{"path":"/pages/services/project/headline","is_dir":false,"children":[]},{"path":"/pages/services/project/text","is_dir":false,"children":[]},
{"path":"/pages/services/project/test/","is_dir":true,"children":[{"path":"/pages/services/project/test/text","is_dir":false,"children":[]},
{"path":"/pages/services/project/test/picture","is_dir":false,"children":[]}]}]};

json.children.forEach(function (child) {
	out(goToDeepestPoint(child).path);
});



function goToDeepestPoint(node) {
    if (node.is_dir)
        return goToDeepestPoint(node.children[0]);
    else 
        return node;
}

function out()
{
    var args = Array.prototype.slice.call(arguments, 0);
    document.getElementById('output').innerHTML += args.join(" ") + "\n";
}
<pre id="output"></pre>

Ответ 1

Я был занят игрой с вашим оригинальным вопросом и получил эту работу:

goToDeepestPoint(json);

function goToDeepestPoint(node) {
    if (node.is_dir)
        node.children.forEach(function (child) {
    goToDeepestPoint(child);
});
    else 
        return out(node.path);
}

Может быть не уместно в свете вашего редактирования, но стыдно тратить его!

Ответ 2

var json = {"path":"/pages/services/project", "is_dir":true, "children":[{"path":"/pages/services/project/headline","is_dir":false,"children":[]},{"path":"/pages/services/project/text","is_dir":false,"children":[]},
{"path":"/pages/services/project/test/","is_dir":true,"children":[{"path":"/pages/services/project/test/text","is_dir":false,"children":[]},
{"path":"/pages/services/project/test/picture","is_dir":false,"children":[]}]}]};

function getPaths(obj){
    let foundPaths = [];
    if(obj.children.length > 0){
        obj.children.forEach(function (element){
           let childPaths = getPaths(element);
           foundPaths = foundPaths.concat(childPaths);
        });
        return foundPaths;
   } else {
      foundPaths.push(obj.path);
      return foundPaths;
   }
}

let paths = getPaths(json);

document.getElementById('output').innerHTML += paths.join("\n");
<pre id="output"></pre>

Ответ 3

Рабочее решение

:

var json = {"path":"/pages/services/project", "is_dir":true, "children":[{"path":"/pages/services/project/headline","is_dir":false,"children":[]},{"path":"/pages/services/project/text","is_dir":false,"children":[]},
{"path":"/pages/services/project/test/","is_dir":true,"children":[{"path":"/pages/services/project/test/text","is_dir":false,"children":[]},
{"path":"/pages/services/project/test/picture","is_dir":false,"children":[]}]}]};

json.children.forEach(function (child) {
    goToDeepestPoint(child);
});



function goToDeepestPoint(node) {
    if (node.is_dir){
      for(var i=0;i<node.children.length;i++){
        goToDeepestPoint(node.children[i]);
      }
    }        
    else {
        out(node.path);
    }
}

function out()
{
    var args = Array.prototype.slice.call(arguments, 0);
    document.getElementById('output').innerHTML += args.join(" ") + "\n";
}

Ответ 4

Я поделюсь своим ответом, потому что он имеет отношение к тому, над чем я работал в данный момент, - он требует более функционального подхода, потому что это просто то, что я изучал.

Стойкие итераторы

Итераторы с явным комментарием JavaScript меня огорчают, поэтому мы можем реализовать постоянный интерфейс итератора, используя наши собственные типы Yield и Return. Используется тип Memo, но это просто детали оптимизации.

const Memo = (f, memo) => () =>
  memo === undefined
    ? (memo = f (), memo)
    : memo

const Yield = (value, next = Return) =>
  ({ done: false, value, next: Memo (next) })
  
const Return = value =>
  ({ done: true, value })
  
// example use
const ArrayIterator = (xs = []) =>
  xs.length === 0
    ? Return ()
    : Yield (xs [0], () => ArrayIterator (xs.slice (1)))
    
const it =
  ArrayIterator ([1,2,3])

console.log (it.value) // 1
console.log (it.value) // 1
console.log (it.next () .value) // 2
console.log (it.next () .value) // 2