7. Агрегация 2
Научиться получать составной (массив) результат обхода дерева
Попрактикуемся ещё с одним вариантом агрегации данных на файловых системах. Напишем функцию, которая принимает на вход директорию и возвращает список директорий первого уровня вложенности и количество файлов внутри каждой из них, включая все поддиректории
const tree = mkdir('/', [
mkdir('etc', [
mkdir('apache'),
mkdir('nginx', [
mkfile('nginx.conf'),
]),
]),
mkdir('consul', [
mkfile('config.json'),
mkfile('file.tmp'),
mkdir('data'),
]),
mkfile('hosts'),
mkfile('resolve'),
]);
console.log(getSubdirectoriesInfo(tree));
// => [['etc', 1], ['consul', 2]]
Внутри себя эта задача распадается на две:
- Подсчёт количества файлов внутри директории
- Вызов функции подсчёта файлов на каждой из поддиректорий
Начнём с подсчёта количества файлов. Это классическая задача на агрегацию:
const getFilesCount = (node) => {
if (isFile(node)) {
return 1;
}
const children = getChildren(node);
const descendantCounts = children.map(getFilesCount);
return _.sum(descendantCounts);
};
Следующий шаг заключается в том, чтобы извлечь всех детей из исходного узла и к каждому из них применить подсчёт:
const getSubdirectoriesInfo = (tree) => {
const children = getChildren(tree);
const result = children
// Нас интересуют только директории
.filter(isDirectory)
// Запускаем подсчёт для каждой директории
.map((child) => [getName(child), getFilesCount(child)]);
return result;
};
То есть мы обратились к детям напрямую сначала отфильтровав их, а затем выполнили отображение на необходимый массив, содержащий для каждой директории имя и количество файлов в нем.
Упражнение
Во многих операционных системах (Linux, MacOS) существует утилита du. Она умеет подсчитывать занимаемое место указанными файлами и директориями. Например, так:
tmp$ du -sh * 0B com.docker.vmnetd.socket 10M credo 4.0K debug.mjs 0B filesystemui.socket 4.0K index.php 37M node_modules 88K package-lock.json 22M taxdome
Перед тем, как делать упражнение, обязательно попробуйте поиграйте с этой утилитой в терминале, посмотрите её опции через man du. Экспериментировать нужно в локально установленной операционной системе.
du.js
Реализуйте и экспортируйте по умолчанию функцию, которая принимает на вход директорию, а возвращает список узлов вложенных, (директорий и файлов) в указанную директорию на один уровень, и место которое, они занимают. Размер файла задается в метаданных. Размер директории складывается из сумм всех размеров файлов, находящихся внутри во всех поддиректориях. Сами директории размера не имеют.
Пример
import { mkdir, mkfile } from '@hexlet/immutable-fs-trees';
import du from '../du.js';
const tree = mkdir('/', [
mkdir('etc', [
mkdir('apache'),
mkdir('nginx', [
mkfile('nginx.conf', { size: 800 }),
]),
mkdir('consul', [
mkfile('config.json', { size: 1200 }),
mkfile('data', { size: 8200 }),
mkfile('raft', { size: 80 }),
]),
]),
mkfile('hosts', { size: 3500 }),
mkfile('resolve', { size: 1000 }),
]);
du(tree);
// [
// ['etc', 10280],
// ['hosts', 3500],
// ['resolve', 1000],
// ]
Примечания
- Обратите внимание на структуру результирующего массива. Каждый элемент — массив с двумя значениями: именем директории и размером файлов внутри.
- Результат отсортирован по размеру в обратном порядке. То есть сверху самые тяжёлые, внизу самые лёгкие.
Подсказки
Хештеги