Created
April 2, 2017 23:23
-
-
Save chris-gaona/9eba1b5f83ecf7d13c99eadd8acf8f3f to your computer and use it in GitHub Desktop.
Various ways to utilize the amazing reduce function on arrays in javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// create an object using reduce function on array with count of each item | |
var votes = [ | |
'angular', | |
'angular', | |
'react', | |
'react', | |
'react', | |
'angular', | |
'ember', | |
'vanilla', | |
'angular' | |
]; | |
var initialValue = {}; | |
// function (accumulator, initialValue) | |
var reducer = function (tally, vote) { | |
// if item does not already exist as key in object | |
if (!tally[vote]) { | |
// add key to the object with value of 1 | |
tally[vote] = 1; | |
// else if it already exists in the object | |
} else { | |
// increment the value of the key | |
tally[vote] = tally[vote] + 1; | |
} | |
// always have to return | |
return tally; | |
} | |
var results = votes.reduce(reducer, initialValue); | |
console.log(results); | |
//////////////////// | |
//////////////////// | |
// examples of using .map, .filter, and .reduce | |
// .reduce can be a large performance boost if you are iterating over a large array as you can do map and filter during one iteration through the array | |
var data = [1, 2, 3, 4, 5, 6]; | |
var doubleMapped = data.map(function (item) { | |
return item * 2; | |
}); | |
console.log(doubleMapped); | |
var evenFiltered = data.filter(function (item) { | |
// if item is divisible by 2 return it | |
return (item % 2 === 0); | |
}); | |
console.log(evenFiltered); | |
///////////////////// | |
///////////////////// | |
// Big Data example....reduce can greatly increase performance | |
var bigData = []; | |
for (var i = 0; i < 1000000; i++) { | |
bigData[i] = i; | |
} | |
console.time('bigData'); | |
var filterMappedBigData = bigData.filter(function(value) { | |
return value % 2 === 0; | |
}).map(function(value) { | |
return value * 2; | |
}); | |
console.timeEnd('bigData'); | |
console.time('bigDataReduce'); | |
var reducedBigData = bigData.reduce(function(acc, value) { | |
// performing filter function first for those divisible by 2 | |
if (value % 2 === 0) { | |
// performing map to multiple all items by 2 | |
acc.push(value * 2); | |
} | |
return acc; | |
// initialize reduce as an empty array below | |
}, []); | |
console.timeEnd('bigDataReduce'); | |
/////////////////// | |
/////////////////// | |
// create sum all array of number using reduce | |
function sumReducer(accumulator, value) { | |
return accumulator + value; | |
} | |
// initialize reduce as 0 | |
var sum = data.reduce(sumReducer, 0); | |
console.log(sum); | |
// find the mean of an array of numbers using reduce | |
// uses extra parameters of reduce | |
function meanReducer(accumulator, value, index, array) { | |
var intermediaryValue = accumulator + value; | |
if (index === array.length - 1) { | |
return intermediaryValue / array.length; | |
} | |
return intermediaryValue; | |
} | |
var meanData = [1, 2, 3, 3, 4, 5, 3, 1]; | |
var mean = meanData.reduce(meanReducer, 0); | |
console.log(mean); | |
////////////////// | |
////////////////// | |
// real world example using reduce to flatten and flatmap an array of objects with arrays in them | |
var input = [ | |
{ | |
title: "Batman Begins", | |
year: 2005, | |
cast: [ | |
"Christian Bale", | |
"Michael Caine", | |
"Liam Neeson", | |
"Katie Holmes", | |
"Gary Oldman", | |
"Cillian Murphy" | |
] | |
}, | |
{ | |
title: "The Dark Knight", | |
year: 2008, | |
cast: [ | |
"Christian Bale", | |
"Heath Ledger", | |
"Aaron Eckhart", | |
"Michael Caine", | |
"Maggie Gyllenhal", | |
"Gary Oldman", | |
"Morgan Freeman" | |
] | |
}, | |
{ | |
title: "The Dark Knight Rises", | |
year: 2012, | |
cast: [ | |
"Christian Bale", | |
"Gary Oldman", | |
"Tom Hardy", | |
"Joseph Gordon-Levitt", | |
"Anne Hathaway", | |
"Marion Cotillard", | |
"Morgan Freeman", | |
"Michael Caine" | |
] | |
} | |
]; | |
// reduce all cast arrays to only show each start once and convert to only 1 array | |
var stars = input.reduce(function (acc, value) { | |
// for each cast array iterate through each star | |
value.cast.forEach(function (star) { | |
// if the star does not exist in the new array | |
if (acc.indexOf(star) === -1) { | |
// add the star | |
acc.push(star); | |
} | |
}); | |
// return the new flattened array | |
return acc; | |
}, []); | |
console.log(stars); | |
////////////////// | |
////////////////// | |
// using a pipeline of functions and reduce | |
function increment(input) { return input + 1;} | |
function decrement(input) { return input - 1; } | |
function double(input) { return input * 2; } | |
function halve(input) { return input / 2; } | |
var initial_value = 1; | |
// pipeline contains each function found above | |
var pipeline = [ | |
increment, | |
increment, | |
increment, | |
double, | |
increment, | |
increment, | |
halve | |
]; | |
var final_value = pipeline.reduce(function(acc, fn) { | |
// acc contains each value returned from the previous iteration | |
// passes in each acc to the next function | |
return fn(acc); | |
}, initial_value); | |
var reversed = pipeline.reduceRight(function(acc, fn) { | |
// reduceRight starts at the last item in the array & moves the other way | |
return fn(acc); | |
}, initial_value); | |
console.log(final_value, reversed); | |
///////////////////// | |
///////////////////// | |
// dealing with data that does not have the same data structure | |
var characters = [ | |
{ | |
name: "luke skywalker", | |
jedi: true, | |
parents: { | |
father: { | |
jedi: true | |
}, | |
mother: { | |
jedi: false | |
} | |
} | |
}, | |
{ | |
name: "han solo", | |
jedi: false, | |
parents: { | |
father: { | |
jedi: false | |
}, | |
mother: { | |
jedi: false | |
} | |
} | |
}, | |
{ | |
name: "anakin skywalker", | |
jedi: true, | |
parents: { | |
mother: { | |
jedi: false | |
} | |
} | |
} | |
]; | |
function fatherWasJedi(character) { | |
var path = "parents.father.jedi"; | |
// split creates array like this: ['parents', 'father', 'jedi'] | |
return path.split(".").reduce(function(obj, field) { | |
// 1st iteration: | |
// obj = parents --> if parents key exists | |
// return parents[father] | |
// 2nd iteration: | |
// obj = parents[father] --> if parents.father key exists | |
// return parents[father][jedi] | |
// 3rd iteration: | |
// obj = parents[father][jedi] --> if parents.father.jedi key exists | |
// return parents[father][jedi] | |
// else return false instead of returning undefined & throwing an exception | |
if (obj) { | |
return obj[field]; | |
} | |
return false; | |
}, character); | |
} | |
characters.forEach(function(character) { | |
console.log(character.name + "'s father was a jedi:", fatherWasJedi(character)); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment