Skip to content

Instantly share code, notes, and snippets.

@manavm1990
Last active March 19, 2020 20:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manavm1990/3fd932151def3a5a3fb754ccaa291783 to your computer and use it in GitHub Desktop.
Save manavm1990/3fd932151def3a5a3fb754ccaa291783 to your computer and use it in GitHub Desktop.
Misc. data transformation utility functions.
import { promises as fs } from "fs";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
// (https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-when-using-the-experimental-modules-flag/50052194#50052194)
const __dirname = dirname(fileURLToPath(import.meta.url));
/**
* Create a 'data object' based on JSON files.
* @param keys
* @param JSONDir
* @return {Promise} The πŸ”‘s will be the names of the files in the given directory πŸ‘†πŸ½ and values will be the JSON data, of course πŸ™„.
* @throws Will throw error if cannot read in all data
*/
function readDataFromJSONFiles(keys, JSONDir) {
return (
Promise.all(
keys
// Strip keys from full filenames
.map(key => key.substring(0, key.indexOf(".")))
// Create data object by asynchronously reading the JSON data in each file.
.map(async key => ({
[key]: JSON.parse(await fs.readFile(`./${JSONDir}/${key}.json`))
}))
)
/**
* 'Promise.all' will have an Array from 'map' πŸ‘†πŸ½.
* Each element will be a separate object.
* From this, we 'combine' that into the data object that we need.
*/
.then(fileContents =>
fileContents.reduce(
(accumulator, data) => ({ ...accumulator, ...data }),
{}
)
)
.catch(error => {
throw error;
})
);
}
/**
* Filters data by removing keys that have values that don't include some string.
* @param {Object} o
* @param {Object} o.data
* @param {string} o.key
* @param {string} o.str
*/
export function filterByStringInclusionCondition({ data, key, str } = {}) {
return data.filter(entry => entry[key].includes(str));
}
/**
* @param {string} dir - name of directory containing the JSON data.
* @return {Promise|String}
*/
export async function loadJSON(dir = "JSON") {
let keys;
try {
keys = await fs.readdir(join(__dirname, dir));
} catch (error) {
console.error(`Error reading directory, ${dir}.`, error);
}
try {
return await readDataFromJSONFiles(keys, dir);
} catch (error) {
return `Error reading in JSON files: ${error}`;
}
}
export function stripBackslashes(str) {
return str.replace(/\\/g, "");
}
export function stripHTML(str) {
return str.replace(/(<([^>]+)>)/gi, "");
}
export function stripHTMLCharacterCodes(str) {
return str.replace(/&[A-Za-z]+(?<!&gt|&lt);/gi, "");
}
// TODO: How to curry multiple CBs?
/**
* Update values of given πŸ”‘s (each 'key' should be present already) in an object.
* @param {Object} data
* @param {Array} keys
* @param {Function} cb - the 'update' to perform
* @return {Object}
*/
export function updateSpecifiedKeys({ data, keys, cb } = {}) {
return data.map(d =>
// For every 'd', update all of the VALUES for some specified ARRAY of πŸ”‘s...'reduce' πŸ”‘s down to just 1 'updated object'.
keys.reduce(
(updatedObject, currentKey) => ({
...d,
...updatedObject,
...{ [currentKey]: cb(d[currentKey]) }
}),
{}
)
);
}
export function writeJSONData(data, fileName) {
fs.writeFile(`./${fileName}.json`, JSON.stringify(data, null, 2))
.then(() => {
console.log("Rote file!");
})
.catch(error => {
console.error(`Error riting file: ${error}`);
});
}
@manavm1990
Copy link
Author

@manavm1990
Copy link
Author

This assumes that the πŸ”‘ s exist in each data Object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment