Code Examples for Reading 16
Download
You can also download a ZIP file containing this code.
Words1.ts
import fs from 'fs';
import path from 'path';
/**
* Words example: familiar TS implementation
*/
/**
* Find names of all files in the filesystem subtree rooted at folder.
* @param folder root of subtree, requires fs.lstatSync(folder).isDirectory() === true
* @returns list of names of all ordinary files (not folders) that have folder as
* their ancestor
*/
function allFilesIn(folder:string):Array<string> {
let files:Array<string> = [];
for (let child of fs.readdirSync(folder)) {
const fullNameOfChild = path.join(folder, child);
if (fs.lstatSync(fullNameOfChild).isDirectory()) {
files = files.concat(allFilesIn(fullNameOfChild));
} else if (fs.lstatSync(fullNameOfChild).isFile()) {
files.push(fullNameOfChild);
}
}
return files;
}
/**
* Filter a list of files to those that end with suffix.
* @param filenames list of filenames
* @param suffix string to test
* @returns a new list consisting of only those files whose names end with suffix
*/
function onlyFilesWithSuffix(filenames:Array<string>, suffix:string):Array<string> {
let result:Array<string> = [];
for (let f of filenames) {
if (f.endsWith(suffix)) {
result.push(f);
}
}
return result;
}
/**
* Find all the non-word-character-separated words in files.
* @param filenames list of files (all non-null)
* @returns list of words from all the files
* @throws IOException if an error occurs reading a file
*/
function getWords(filenames:Array<string>):Array<string> {
let words:Array<string> = [];
for (let f of filenames) {
const data = fs.readFileSync(f, { encoding: "utf8", flag: "r" });
const lines = data.split(/\r?\n/);
for (let line of lines) {
// split on \W (non-word characters, like spaces and punctuation)
for (let word of line.split(/\W+/)) {
// split can return empty strings, so omit them
if (word.length > 0) {
words.push(word);
}
}
}
}
return words;
}
let allFiles = allFilesIn(".");
let tsFiles = onlyFilesWithSuffix(allFiles, ".ts");
let words = getWords(tsFiles);
for (let s of words) { console.log(s); }
Words2.ts
import fs from 'fs';
import path from 'path';
/**
* Words example: TS implementation with map/filter/reduce
*/
/**
* Find all files in the filesystem subtree rooted at folder.
* @param folder root of subtree, requires folder.isDirectory() == true
* @returns stream of all ordinary files (not folders) that have folder as
* their ancestor
*/
function allFilesIn(folder:string):Array<string> {
let children: Array<string> =
fs.readdirSync(folder)
.map(f => path.join(folder, f));
let descendants: Array<string> = children
.filter(f => fs.lstatSync(f).isDirectory())
.flatMap(allFilesIn);
return [
...descendants,
...children.filter(f => fs.lstatSync(f).isFile())
];
}
/**
* Make a filename suffix testing predicate.
* @param suffix string to test
* @returns a predicate that returns true iff the filename ends with suffix.
*/
function endsWith(suffix:string): (filename:string) => boolean {
return (filename: string) => filename.endsWith(suffix);
}
let filenames: Array<string> = allFilesIn(".")
.filter(s => s.endsWith(".ts"));
let fileContents: Array<Array<string>> = filenames.map(f => {
const data = fs.readFileSync(f, { encoding: "utf8", flag: "r" });
return data.split(/\r?\n/);
});
let lines: Array<string> = fileContents.flatMap(x => x);
let words: Array<string> = lines.flatMap(line => line.split(/\W+/)
.filter(s => s.length > 0));
words.forEach(s => console.log(s));