Some helpful tips, tricks, good practices and ready-made solutions in Javascript / Typescript
const numbers = [29.76, 41.85, 46.5];
const sum = numbers.reduce((total, amount) => total + amount);
sum // 118.11
// Other way
const sum = (acc, value) => acc + value;
const mySum = numbers.reduce(sum, 0);
const numbers = [29.76, 41.85, 46.5];
const average = (array) => array.reduce((a, b) => a + b) / array.length;
const avg = average(numbers)
avg // 39.37
// 2nd way
const avg = array.reduce(sum, 0) / array.length;
// 3rd way
const avg2 = (sum, val, id, arr) => {
sum += val;
return id === arr.length - 1 ? sum / arr.length : sum;
};
// Object
const average = arr => {
const sumCount = arr.reduce(
(acc, val) => ({sum: val + acc, count acc.count + 1}),
{sum: 0, count: 0});
return sumCount.sum / sumCount.count;
}
// Array
const average = arr => {
const sumCount = arr.reduce(
(acc, val) => ({sum: acc[0] + val, count acc[1] + 1}),
[0, 0]);
return sumCount[0] / sumCount[1]
}
const brands = ['suzuki', 'suzuki', 'mercedes', 'audi', 'mercedes'];
const brandsCount = arr.reduce(
(acc, val) => ({ ...acc, [val]: acc[val] ? acc[val] + 1 : 1}),
{}
);
{
audi: 1
mercedes: 2
suzuki: 2
}
const nums = [1, 2, 3, 4, 5, 6, 7, 8];
const [min, max] = nums.reduce(
(acc, cur) => [Math.min(acc[0], cur), Math.max(acc[1], cur)],
[Infinity, 0]
);
// min: 1
// max: 8
const numbers = [1, 2, 3, 4, 5];
const evenOddSum = array => array.reduce((acc, cur, id) => (acc[id & 1] += cur,acc), [0,0])
const sum = evenOddSum(numbers);
sum // [9, 6]
const objectsArr = [
{
id: 1,
name: 'Peter',
proffesion: 'plumber',
},
{
id: 2,
name: 'Mark',
proffesion: 'baker',
},
{
id: 3,
name: 'Greg',
proffesion: 'firefighter',
},
];
const objectsByIdArr = objectsArr.reduce(
(acc, curr) => ({ ...acc, [curr.id]: curr }),
{}
);
objectsByIdArr {
'1': { id: 1, name: 'Peter', proffesion: 'plumber' },
'2': { id: 2, name: 'Mark', proffesion: 'baker' },
'3': { id: 3, name: 'Greg', proffesion: 'firefighter' }
}
const data = [
{a: 'pig', b: 'dog', c: ['apple','grape']},
{a: 'cat', b: 'seal', c: ['banana','orange']},
{a: 'fish', b: 'cow', c: ['coconut','pineapple']}
];
const fruitsOnly = data.reduce((totalFruits, obj) => {
obj.fruits.forEach((f) => totalFruits.push(f))
return totalFruits;
}, [])
fruitsOnly: [
'apple', 'grape',
'banana', 'orange',
'blueberry', 'raspberry',
'coconut', 'pineapple'
]
const reverseString = str => str.split('').reduceRight((x, y) => x + y, '');
const range = (from, to, including = true) => {
const scope = including ? to - from + 1 : to - from - 1;
return Array(scope)
.fill(0)
.map((_, id) => (including ? from + id : from + id + 1));
};
const cities = [
{name: 'New York', long:40.7128, lat: 74.0060},
{name: 'Tokyo', long:25.2048, lat: 55.2708},
{name: 'Krakow', long:50.0647, lat: 19.9450},
]
const avgLong = average(cities.map(city => city.long))
const avgLat = average(cities.map(city => city.lat))
const numbers = ['4.2332', '12.221', '2131.4367'].map(parseFloat);
// Doesnt work with parseInt! which takes more args
const ALPHABET = range('A'.charCodeAt(), 'Z'.charCodeAt()).map(code => String.fromCharCode(code));
const numbers = [1, 2, [[3, (4)[(5, 6)]][(7, 8)]]];
const oneLevelDeep = numbers.flat(1);
const twoLevelsDeep = numbers.flat(2);
const flattedTotally = numbers.flat(Infinity);
const apiAnswer = [
{
id: 122232,
name: 'John Doe',
groups: [
{
groupId: 121221,
groupName: 'Doplphins',
participants: [{ participantId: 3846864, name: 'Max' }],
},
],
},
{
id: 122233,
name: 'Marry Cohen',
groups: [
{
groupId: 232131,
groupName: 'Alaska Team',
participants: [{ participantId: 2644487, name: 'Merry' }],
},
],
},
{
id: 122234,
name: 'Christine Malone',
groups: [
{
groupId: 12121221,
groupName: 'Tigers',
participants: [
{
participantId: 50720006,
name: 'Harry',
},
{
participantId: 4899911,
name: 'Barry',
},
{
participantId: 4899966,
name: 'Lissie',
},
],
},
],
},
];
apiAnswer.map(x => x.groups)
.flat()
.map(y => y.participants)
.flat()
[
{
name: 'Max',
participantId: 3846864,
},
{
name: 'Merry',
participantId: 2644487,
},
{
name: 'Harry',
participantId: 50720006,
},
{
name: 'Barry',
participantId: 4899911,
},
{
name: 'Lissie',
participantId: 4899966,
},
]
apiAnswer
.flatMap(x => x.groups)
.flatMap(y => y.participants)
[1, 2, 3, 0].filter(Boolean)
// result [1, 2, 3]
const none = (arr, fn) => arr.every(v => !fn(v));
const once = (once) => {
let done = false;
return (...args) => {
if (!done) {
done = true;
once(...args);
}
};
};
const once = (fn) => {
return (...args) => {
fn && fn(...args);
fn = null;
};
};
const onceAndAfter = (once, after) => {
let done = false;
return (...args) => {
if (!done) {
done = true;
once(...args);
} else {
after(...args);
}
};
};
const factorialByRange = n => range(1, n).reduce((x, y) => x * y, 1);
let cache = [];
const fibo = (n) => {
if (cache[n] === undefined) {
if (n === 0) {
cache[0] = 0;
} else if (n === 1) {
cache[1] = 1;
} else {
cache[n] = fibo(n - 2) + fibo(n - 1);
}
}
return cache[n];
};
const cities = [
{ name: 'New York', long: 40.7128, lat: 74.006 },
{ name: 'Tokyo', long: 25.2048, lat: 55.2708 },
{ name: 'Krakow', long: 50.0647, lat: 19.945 },
];
const avgLong = average(cities.map((city) => city.long));
const avgLat = average(cities.map((city) => city.lat));
const example = {
name: 'Tom',
age: 26,
}
const getField = attr => obj => obj[attr];
const getName = getField('name)';
const getAge = getField('age)';
getName(example) // "Tom"
getAge(example) // 26
// From previous example
cont avgLon = average(cities.map(getField('lon'))); // 38.66076666666667
cont avgLat = average(cities.map(getField('lat')));
// Also see lodash: .get, .property, .propertyOf
const not = fn => (...args) => !fn(...args);
const filterNot = arr => fn => arr.filter(not(fn));
const invert = fn => (...args) => -fn(...args);
const exampleFn = (a, b, c) => `${100 * a + 10 * b + c}`;
const exampleCurried = a => b => c => `${100 * a + 10 * b + c}`;
// Normal way
const sumNumbers = (a, b, c, d) => a + b + c + d;
// sumNumbers(1,2,3,4) => 10
// Currying by hand
const curriedSumNumbers = a => b => c => d => a + b + c + d;
// curriedSumNumbers(1)(2)(3)(4) => 10
const addVAT = (rate, amount) => amount * (1 + rate / 100);
// addVAT(20,500) => 600
// Curried example
const addVATcurried = rate => amount => amount * (1 + rate / 100);
const addFoodVAT = addVATcurried(18);
// addFoodVAT(100) => 118
// Partial application by hand
const sumNumbers = (a, b) => a + b;
const partial = (fn, ...args) => (...moreArgs) => fn(...args, ...moreArgs)
const add1 = partial(sumNumbers, 1);
// add1(2) => 3
// Using js bind
const sumNumbers = (a, b, c, d) => a + b + c + d;
const partiallyAppliedSumNumbers = sumNumbers.bind(null, 1, 2);
// partiallyAppliedSumNumbers(3,4) 10
const otherPartiallyAppliedSumNumbers = partiallyAppliedSumNumbers.bind(null, 3);
// otherPartiallyAppliedSumNumbers(4) => 10
const isInArray = (arr, key) => {
if (arr.length === 0) {
return false;
} else if (arr[0] === key) {
return true;
} else {
return isInArray(arr.slice(1), key);
}
}
const numberArr = [1, 3, 4];
// isInArray(numberArr, 3) => true
// isInArray(numberArr, 3) => false
const isInArray2 = (arr, key) => arr.length === 0 ? false : arr[0] === key || isInArray2(arr.slice(1), key);
const arra = [1, 3, 4];
// isInArray(arra, 3) => true
// isInArray(arra, 2) => false
const isInArray3 = (arr, key) => arr.length && (arr[0] === key || isInArray2(arr.slice(1), key))
// this will return 0 (array length) if there's no searched value
const powerN = (base, power) => {
if(power === 0) {
return 1;
} else if (power % 2) {
return base * powerN(base, power-1);
} else {
return powerN(base * base, power / 2);
}
}
// powerN(2, 10) => 1024