Last active
May 12, 2017 13:20
-
-
Save MaraAlexa/f411cd6c9cea2daea6a9f6c3d89f45c1 to your computer and use it in GitHub Desktop.
Reduce Data with Array.reduce()
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
// 1. Transform a nested list into a single list = Flattten a list of lists | |
var data = [[1, 2, 3], [4, 5, 6], [7, 8]]; | |
// flaten this array of arrays into a SINGLE array | |
var flattenedData = data.reduce(function(acc, value){ | |
return acc.concat(value); | |
},[]); | |
console.log(flattenedData); // [1, 2, 3, 5, 6, 7, 8] | |
//_______________________________________________________________________________________________________ | |
// 2. Flaten a list of complex objects => Real Case => Called a Flatmap | |
// a Flatmap takes in a list of items(values) and returns each of those values into an Array | |
var complexData = [ | |
{ | |
title: "Batman Begins", | |
year: 2005, | |
cast: [ | |
"Michael Caine", | |
"Gary Oldman", | |
"Cillian Murphy" | |
] | |
}, | |
{ | |
title: "The Dark Knight", | |
year: 2008, | |
cast: [ | |
"Michael Caine", | |
"Christian Bale", | |
"Morgan Freeman" | |
] | |
}, | |
{ | |
title: "The Dark Knight Rises", | |
year: 2012, | |
cast: [ | |
"Christian Bale", | |
"Michael Caine" | |
] | |
} | |
]; | |
// NAIVE way to get all the famous stars | |
var stars = input.reduce(function(acc, value){ | |
return acc.concat(value.cast); // you get all the values from the cast including the repeated ones | |
},[]); | |
console.log(stars); | |
/* [ | |
"Michael Caine", | |
"Gary Oldman", | |
"Cillian Murphy", | |
"Michael Caine", | |
"Christian Bale", | |
"Morgan Freeman", | |
"Christian Bale", | |
"Michael Caine" | |
] */ | |
// SMART way: only include each star once | |
var stars = complexData.reduce(function(acc, value) { | |
value.cast.forEach(function(star) { | |
if (acc.indexOf(star) === -1) { // if the index of star does NOT EXist yet in the acc | |
acc.push(star); // push the star into the acc array | |
} | |
}); | |
return acc; | |
}, []); | |
console.log(stars); // ["Michael Caine", "Gary Oldman", "Cillian Murphy", "Christian Bale", "Morgan Freeman"] | |
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
// Take an array and reduce it into a mean value | |
// mean = a number that represents the average value of a set of numbers => [1,2,3] = (1+2+3) / 3 = 2 | |
// GOOD way - in 2 steps | |
var data = [1, 2, 3, 1]; | |
// find the sum value | |
var sum = data.reduce(function(acc, value) { | |
return acc + value; // 0 + 1+2+3+1 = 7 | |
}, 0); | |
// find the average value | |
var mean = sum / data.length; // 7 / 4 = 1.75 | |
// ____________________________________________________________________________________ | |
// BETTER way - in 1 step | |
// REDUCE always returns the last value of the iteration | |
// so before the last value is returned, we need to sneak in the / operation | |
var myMean = data.reduce(function(acc, value, index, array){ | |
// need a var to hold the accumulated value up until the last value | |
var intermediaryValue = acc + value; // gives the intermidiary values for the accumulator 0 + 1+2+3= 6 | |
// the logic to change the value of the last value returned (for the last iteration): | |
if(index === array.length - 1) { // if you are at the last item in the array | |
var lastValue = intermidiaryValue / array.length; // (acc + value) / 4 => (6+1) / 4 = 1.75 | |
return lastValue; // 1.75 | |
} | |
// if this is NOT the last iteration | |
// 1st : 0 + 1 = 1 | |
// 2nd: 1 + 2 = 3 | |
// 3rd: 3 + 3 = 6 | |
// 4th: run IF case | |
return intermidiaryValue; // 6 | |
}, 0) | |
console.log(myMean); // 1.75 |
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
// ---- * when you need a MODDIFIED ARRAY of the SAME LENGTH * ---- | |
var data = [1, 2, 3]; | |
// 1. with REDUCE | |
var doubled = data.reduce(function(acc, value) { | |
acc.push(value * 2); | |
return acc; | |
}, []); | |
console.log(doubled); // [2, 4, 6] | |
// 2. with MAP | |
var doubleMapped = data.map(function(item){ | |
return item * 2; | |
}) | |
console.log(doubleMapped); // [2, 4, 6] | |
// ---- * need a SHORTER ARRAY that contains some subset of those values (filter an array for something) * ---- | |
var data2 = [1, 2, 3, 4, 5, 6]; | |
// 1. with REDUCE | |
var even = data2.reduce(function(acc, item){ | |
if(item % 2 === 0) { | |
acc.push(item); | |
} | |
return acc; | |
}, []); | |
console.log(even); // [2, 4, 6] | |
// 2. with FILTER | |
var evenFiltered = data2.filter(function(item){ | |
return item % 2 === 0; | |
}); | |
console.log(evenFiltered); // [2, 4, 6] | |
// ---------- * need to FILTER an array and MODIFY it * ---------- | |
// 1. with FILTER and MAP ( you iterate 2 times) | |
var filterMapped = data2.filter(function(item) { | |
return item % 2 === 0; // [2, 4, 6] | |
}).map(function(item) { | |
return item * 2; // [4, 8, 12] | |
}) | |
console.log(filterMapped); // [4, 8, 12] | |
// * ---- Use REDUCE to modify LARGE DATASETS * ---- | |
// 2. with REDUCE (shorter time to run = good for big set of Data)- > iterate only once | |
var bigData = [1, 2, 3 ,4, ..., 999999, 1000000 ]; | |
var reducedBigData = bigData.reduce(function(acc, item) { | |
if ( item % 2 === 0) { | |
acc.push(item * 2); | |
} | |
return acc; | |
}, []); | |
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
// Reduce an array into a single object -> {'angular': 3, 'react': 4, 'ember': 1. 'vanilla': 1} | |
var votes = [ | |
"angular", | |
"angular", | |
"react", | |
"react", | |
"react", | |
"angular", | |
"ember", | |
"react", | |
"vanilla" | |
]; | |
// ---- * you need AN OBJECT that gives the number of votes for each framework: 'angular': 2, 'react': 3 * ---- | |
// in 2 Steps: | |
var initialValue = {}; // set up an empty obj as the initial value of the accumulator | |
var reducer = function(acc, vote){ // gets each vote one after another | |
if(!acc[vote]){ // if the key 'angular' does not yet exist in the accumulator obj | |
acc[vote]= 1; // then create a new key for the acc obj with 1 as its value; -> {'angular': 1} | |
} else {// if 'angular' already exists in the acc obj | |
acc[vote] = acc[vote] + 1; // increment its value ->'angular': 2 | |
} | |
return acc; // VERY IMPORTANT | |
}; | |
var result = votes.reduce(reducer, initialValue); // | |
// 1st->{}; | |
// 2nd->{'angular': 1} | |
// 3rd->{'angular': 2}; | |
// 4th->{'angular': 2, 'react': 1}; | |
// 5th-> {'angular': 2, 'react': 2}; | |
// 6th....etc...9th | |
console.log(result); // last iteration {'angular': 3, 'react': 4, 'ember': 1. 'vanilla': 1}; | |
//_____________________________________________________________________________________________________________ | |
// in 1 step: BETTER | |
var singleObj = votes.reduce(function(acc, vote){ | |
// if the vote does not yet exist in the obj accumulator as a key property => 'angular' is not yet in the acc object | |
if(!acc[vote]) { // if key does Not yet exist; -> !acc['angular'] | |
// create it as a new key property with 1 as its value; | |
acc[vote] = 1; // create new key: acc['angular'] = 1; => acc = {'angular': 1, ...} | |
} | |
else { // if the vote already exists as a key in the accumalator obj | |
acc[vote] = acc[vote] + 1; // increment its value: acc['angular'] = 2; => acc = {'angular': 2, ...} | |
} | |
return acc; // don't forget to return the object !! this runs for each item (vote) in the array | |
},{}); | |
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
// Transform an Array of numbers into a SINGLE Value: [15, 3, 20] => 38 | |
var data = [15, 3, 20]; | |
// In 2 steps: | |
var reducer = function((accumulator, item) { // this func runs for each item in the array | |
return accumulator + item; // 15 + 3 + 20 = 38 | |
} | |
var initialValue = 0; // you need an initial value for the accumulator | |
var total = data.reduce(reducer, initialValue); // how REDUCE works | |
// REDUCE returns only the last value of the accumulator | |
// the accumulator starts with 0 and adds up each value until the end of the array is reached | |
console.log("The sum is: ", total); // 38 | |
// ____________________________________________________________________________________________________ | |
// in 1 step: | |
var totalSum = data.reduce(function(acc, item){ // this loop runs for each item | |
return acc + item; // 0+15; 15+3; 18+20 => 38 | |
},0); // 0 is the starting value of the acc needed for the first iteration; acc & item values change with each iteration | |
console.log(totalSum); // 38 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
## Different cases where you might use Array.prototype.reduce() to manipulate Arrays.
Also comparison doing the same manipulation: Array.prototype.filter() vs .filter() + .map()
IMPORTANT!!!
REDUCE has advantage over Filter + Map when using large data sets because with reduce you only iterate once over the data thus shorter run time.