Skip to content

Instantly share code, notes, and snippets.

@coryhouse
Last active October 12, 2018 12:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save coryhouse/866d30b20766d662707431436234d2f5 to your computer and use it in GitHub Desktop.
Save coryhouse/866d30b20766d662707431436234d2f5 to your computer and use it in GitHub Desktop.
Functional JS examples
// 1. Use reduce to avoid multiple iterations
const todoList = ['clean', 'cook', 'workout', 'nap', 'relax'];
// Remove any item that starts with the 'c'
todoList.filter(todo => todo[0] !== 'c');
// Capitalize every item in the todoList
todoList.map(todo => todo[0].toUpperCase() + todo.substr(1));
// Accomplish the above with reduce
// This does the same as above, but with a single iteration
const initialValue = [];
const newList = todoList.reduce((prev, cur) => {
if (cur[0] !== 'c') {
const capitalizedValue = cur[0].toUpperCase() + cur.substr(1);
return prev.concat(capitalizedValue);
}
return prev;
}, initialValue);
console.log(newList)
// Another example of using reduce to avoid multiple iterations
const users = [
{ name: 'Jon', eyes: 'green', type: 'user', age: 23},
{ name: 'Tonya', eyes: 'blue', type: 'admin', age: 53},
{ name: 'Bob', eyes: 'brown', type: 'admin', age: 14},
{ name: 'Jane', eyes: 'brown', type: 'user', age: 51},
{ name: 'Sally', eyes: 'green', type: 'user', age: 18},
{ name: 'Jon', eyes: 'blue', type: 'admin', age: 71}
]
// Could have used filter and map for this, but that would have required two iterations.
// So reduce was more effecient. 👍
const namesAndAgesOfAdminsOver50 = users.reduce((prev, cur) => {
if (cur.age > 50 && cur.type === 'admin') {
return prev.concat({name: cur.name, age: cur.age});
}
return prev
}, [])
console.log(namesAndAgesOfAdminsOver50)
// now, let's use currying so we can specify the adminsOver predicate as a separate well-named function that accepts age as a param.
const adminsOver = age => obj => {
return obj.age > age && obj.type === 'admin';
}
// note that I had to use currying because filter wants a function.
// So adminsOver is partially applied with just the first param (age) specified, and returns a new function with that first param closed over.
const usersOver50 = users.filter(adminsOver(50));
console.log(usersOver50);
// 3. Consider passing map a well-named func (called a function delegate). Reads nicely.
let jsonData = [
{ id: 1, name: "Soda", price: 3.12, cost: 1.04, size: "4oz", },
{ id: 2, name: "Beer", price: 6.50, cost: 2.45, size: "8oz" },
{ id: 3, name: "Margarita", price: 12.99, cost: 4.45, size: "12oz" }
];
const toMenuItem = x => ({name: x.name, price: x.price});
// Note how this reads like a sentence! 👍
let drinkMenu = jsonData.map(toMenuItem);
// 4. Use reduce to get the most expensive item
let mostExpensiveItem = jsonData.reduce((acc, next) => acc.price > next.price ? acc : next);
console.log(mostExpensiveItem)
// Note you can pass reduce a well named method too. This conveys intent clearly.
let byGreatestPrice = (item, next) => item.price > next.price ? item : next;
let mostExpensiveItem2 = jsonData.reduce(byGreatestPrice); // Note how the name conveys what you're reducing the array down to
// 5. Pipe example
const pipe = functions => data => {
return functions.reduce(
(value, func) => func(value),
data
);
}
let cart = [3.12, 45.15, 11.01];
const addSalesTax = (total, taxRate) => (total * taxRate) + total;
const tally = orders => pipe([
x => x.reduce((total, val) => total + val), // sum the order
x => addSalesTax(x, 0.09),
x => `Order Total = ${x.toFixed(2)}` // convert to text
])(orders); // Order Total = 64.62
// try every, some, includes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment