Skip to content

Instantly share code, notes, and snippets.

@chris-gaona
Created April 2, 2017 23:23
Show Gist options
  • Save chris-gaona/9eba1b5f83ecf7d13c99eadd8acf8f3f to your computer and use it in GitHub Desktop.
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
// 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