Skip to content

Instantly share code, notes, and snippets.

@JonathonAshworth
Last active November 4, 2023 13:08
Show Gist options
  • Select an option

  • Save JonathonAshworth/330d288364525d947efc8f8dc5bf7472 to your computer and use it in GitHub Desktop.

Select an option

Save JonathonAshworth/330d288364525d947efc8f8dc5bf7472 to your computer and use it in GitHub Desktop.
Collection of JS Utility Functions
// f of the form v => v
export const objMap = (obj, f) =>
Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, f(v)]));
// f of the form ([k, v]) => [k, v]
export const objMapEntries = (obj, f) =>
Object.fromEntries(Object.entries(obj).map(f));
export const arrDeepMap = (arr, f) => arr.map((x, i, a) => Array.isArray(x) ? arrDeepMap(x, f) : f(x, i, a));
export const arrZip = (a, b) => a.map((ax, ai) => [ax, b[ai]]);
// Immutable deep set on both objects and arrays
export const imSet = (objOrArray, path, valueOrFunc) => {
const multipath = Array.isArray(path) && path.length > 1;
const pathItem = Array.isArray(path) ? path[0] : path; // unwrap single item array
const isFunc = typeof valueOrFunc === "function";
const value = multipath
? imSet(objOrArray[pathItem], path.slice(1), valueOrFunc)
: isFunc ? valueOrFunc(objOrArray[pathItem]) : valueOrFunc;
if (Array.isArray(objOrArray)) {
return [
...objOrArray.slice(0, pathItem),
value,
...objOrArray.slice(pathItem + 1),
];
} else {
return {
...objOrArray,
[pathItem]: value,
};
}
};
// short array accessors
export const aLast = a => a[a.length - 1];
export const aPrev = (a, i) => i === 0 ? a[a.length - 1] : a[i - 1]; // looping previous
export const aNext = (a, i) => i === a.length - 1 ? a[0] : a[i + 1]; // looping next
export const aFront = a => a.slice(0, a.length / 2); // first half
export const aBack = a => a.slice(a.length / 2); // second half
export const aReverse = a => a.slice().reverse(); // immutable reverse
export const singleton = constructor => (...args) => {
let instance = null;
if (instance) return instance;
instance = constructor(...args);
return instance;
}
export const pipe = (x, ...fs) => fs.reduce((_, f) => f(_), x);
const isObj = o => typeof o === 'object' && o !== null && !Array.isArray(o);
// deeply converts from lower snake case (DB) to camel case (JS front end)
// probably brittle, only use on simple data structures
const strCamel = s => s.replace(/([-_][a-z])/g, g => g.slice(-1).toUpperCase());
export const objDeepCamel = obj =>
objMapEntries(obj, ([k, v]) => [strCamel(k), isObj(v) ? objDeepCamel(v) : v]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment