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], // ]
Примечания
- Обратите внимание на структуру результирующего массива. Каждый элемент — массив с двумя значениями: именем директории и размером файлов внутри.
- Результат отсортирован по размеру в обратном порядке. То есть сверху самые тяжёлые, внизу самые лёгкие.
Подсказки
Хештеги