JS: Trees

Theory: Aggregation 2

Let's practice one more data aggregation technique on file systems. Let's write a function that takes a directory as input and returns a list of directories on the first level of nesting and the number of files inside each of them, including all subdirectories.

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]]

This task breaks down into two smaller ones:

  • Implementing the function counting files in a directory
  • Calling this function for each of the subdirectories

Let's start by counting the number of files. This is a classic aggregation task:

const getFilesCount = (node) => {
  if (isFile(node)) {
    return 1;
  }

  const children = getChildren(node);
  const descendantCounts = children.map(getFilesCount);
  return _.sum(descendantCounts);
};

The next step is to extract all the children from the initial node and apply a count to each of them:

const getSubdirectoriesInfo = (tree) => {
  const children = getChildren(tree);
  const result = children
    // We're only interested in directories
    .filter(isDirectory)
    // Counting in each directory
    .map((child) => [getName(child), getFilesCount(child)]);

  return result;
};

I.e., we accessed the children directly by first filtering them, and mapped them to the desired array, which contained the name and number of files for each directory.

Recommended programs