Вы можете преобразовать строку пути в элемент, имеющий родителей и потомков:
const createItem = (path, parent) => ({
children: [],
path,
parent,
});
Затем отсортируйте строки пути так, чтобы корневой путь всех остальных потомков был первым:
const sortedPaths = paths.slice().sort();
Затем уменьшите отсортированные строки пути до карты, содержащей все элементы, но имеющую свойство children, заполненное их фактическими дочерними элементами:
sortedPaths
.filter((path)=>!path.endsWith('.js'))//filter out js files
.map((path) => [path, parentPath(path)])
.slice(1) //remove first, it is root
.reduce((map, [path, parentPath]) => {
const parent = getParent(map, parentPath);
const item = createItem(path, parent);
parent.children.push(item);
return map.set(path, item);
}, new Map().set(sortedPaths[0], createItem(sortedPaths[0])))
Вам нужен только rootNode, чтобы вы могли сделать .get(sortedPaths[0])
дляэта карта.
Если вы передаете корневой узел функции с именем getLastDescendents
, тогда эта функция может рекурсивно проверять дочерние элементы и добавлять только элементы, которые не имеют дочерних элементов.Поскольку у вас есть вложенные элементы, он создаст многомерный массив, который нужно сгладить:
const flatten = (arr) =>
arr.reduce(
(result, item) =>
!Array.isArray(item)
? result.concat(item)
: result.concat(flatten(item)),
[],
);
const getLastDescendents = (rootNode) => {
const recur = (result, node) =>
node.children.length === 0
? result.concat(node)
: result.concat(
node.children.map((node) => recur(result, node)),
);
return flatten(recur([], rootNode));
};
Все вместе это будет выглядеть так:
const paths = [
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\completion-provider.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\export',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\export\\global.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\export\\index.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\export\\local.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\index.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\module',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\module\\babel.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\module\\global.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\module\\index.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\module\\local.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\lookups\\module\\webpack.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\main.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\package-configs.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\filter-lookups-by-text.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\get-exports-from-prefix.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\get-module-from-prefix.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\internal-modules.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\lookup-alias.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\lookup-commonjs.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\path-helpers.js',
'D:\\Program Files\\atom\\.atom\\packages\\autocomplete-modules\\lib\\utils\\regex-patterns.js',
];
const sortedPaths = paths.slice().sort();
const parentPath = (path) =>
path
.split('\\')
.slice(0, -1)
.join('\\');
const getParent = (map, path) =>
map.get(path) || getParent(map, parentPath(path));
const createItem = (path, parent) => ({
children: [],
path,
parent,
});
const rootNode = sortedPaths
.filter((path)=>!path.endsWith('.js'))//filter out js files
.map((path) => [path, parentPath(path)])
.slice(1) //remove first, it is root
.reduce((map, [path, parentPath]) => {
const parent = getParent(map, parentPath);
const item = createItem(path, parent);
parent.children.push(item);
return map.set(path, item);
}, new Map().set(sortedPaths[0], createItem(sortedPaths[0])))
.get(sortedPaths[0]);
const flatten = (arr) =>
arr.reduce(
(result, item) =>
!Array.isArray(item)
? result.concat(item)
: result.concat(flatten(item)),
[],
);
const getLastDescendents = (rootNode) => {
const recur = (result, node) =>
node.children.length === 0
? result.concat(node)
: result.concat(
node.children.map((node) => recur(result, node)),
);
return flatten(recur([], rootNode));
};
console.log(
getLastDescendents(rootNode).map((node) => node.path),
);