forked from loverajoel/jstips
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request loverajoel#253 from darul75/gh-pages
some reminders about reduce function usage
- Loading branch information
Showing
1 changed file
with
121 additions
and
0 deletions.
There are no files selected for viewing
121 changes: 121 additions & 0 deletions
121
_posts/en/2016-xx-xx-reminders-about-reduce-function-usage.md
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
--- | ||
layout: *post | ||
|
||
title: Reduce builtin function usage | ||
tip-number: xx | ||
tip-username: darul75 | ||
tip-username-profile: https://twitter.com/darul75 | ||
tip-tldr: some reminders about using the reduce function | ||
|
||
categories: | ||
- en | ||
--- | ||
|
||
As written in documentation the reduce() method applies a function against an accumulator and each value of the array (from left-to-right) | ||
to reduce it to a single value. | ||
|
||
reduce() function accepts 2 parameters (M: mandatory, O: optional): | ||
|
||
- (M) a callback **reducer function** to be applied that deals with a pair of previous (result of previous computation) and next element until end of the list. | ||
- (O) an **initial value** to be used as the first argument to the first call of the callback. | ||
|
||
So let's see a common usage and later a more sophisticated one. | ||
|
||
### Common usage (accumulation, concatenation) | ||
|
||
We are on Amazon website (prices in $) and our caddy is quite full, let's compute total. | ||
|
||
```javascript | ||
// my current amazon caddy purchases | ||
var items = [{price: 10}, {price: 120}, {price: 1000}]; | ||
|
||
// our reducer function | ||
var reducer = function add(sumSoFar, nextPrice) { return sumSoFar + nextPrice.price; }; | ||
|
||
// do the job | ||
var total = items.reduce(reducer, 0); | ||
|
||
console.log(total); // 1130 | ||
``` | ||
|
||
Optional reduce function parameter was primitive integer type 0 in that first case, but it could have been an Object, an Array...instead of a primitive type, | ||
but we will see that later. | ||
|
||
Now, cool I received a discount coupon of 20$. | ||
|
||
```javascript | ||
var total = items.reduce(reducer,-20); | ||
|
||
console.log(total); // 1110 | ||
``` | ||
|
||
### Advanced usage (combination) | ||
|
||
This second usage example is inspired by Redux [combineReducers](http://redux.js.org/docs/api/combineReducers.html) function [source](https://github.com/reactjs/redux/blob/master/src/combineReducers.js#L93). | ||
|
||
Idea behind is to separate reducer function into separate individual functions and at the end compute a new *single big reducer function*. | ||
|
||
To illustrate this, let's create a single object literal with some reducers function able to compute total prices in different currency $, €... | ||
|
||
```javascript | ||
var reducers = { | ||
totalInDollar: function(state, item) { | ||
state.dollars += item.price; | ||
return state; | ||
}, | ||
totalInEuros : function(state, item) { | ||
state.euros += item.price * 0.897424392; | ||
return state; | ||
}, | ||
totalInPounds : function(state, item) { | ||
state.pounds += item.price * 0.692688671; | ||
return state; | ||
}, | ||
totalInYen : function(state, item) { | ||
state.yens += item.price * 113.852; | ||
return state; | ||
} | ||
// more... | ||
}; | ||
``` | ||
|
||
Then, we create a new swiss knife function | ||
|
||
- responsible for applying each partial reduce functions. | ||
- that will return a new callback reducer function | ||
|
||
```javascript | ||
var combineTotalPriceReducers = function(reducers) { | ||
return function(state, item) { | ||
return Object.keys(reducers).reduce( | ||
function(nextState, key) { | ||
reducers[key](state, item); | ||
return state; | ||
}, | ||
{} | ||
); | ||
} | ||
}; | ||
``` | ||
|
||
Now let's see how using it. | ||
|
||
```javascript | ||
var bigTotalPriceReducer = combineTotalPriceReducers(reducers); | ||
|
||
var initialState = {dollars: 0, euros:0, yens: 0, pounds: 0}; | ||
|
||
var totals = items.reduce(bigTotalPriceReducer, initialState); | ||
|
||
console.log(totals); | ||
|
||
/* | ||
Object {dollars: 1130, euros: 1015.11531904, yens: 127524.24, pounds: 785.81131152} | ||
*/ | ||
``` | ||
|
||
I hope this approach can give you another idea of using reduce() function for your own needs. | ||
|
||
Your reduce function could handle an history of each computation by instance as it is done in Ramdajs with [scan](http://ramdajs.com/docs/#scan) function | ||
|
||
[JSFiddle to play with](https://jsfiddle.net/darul75/81tgt0cd/) |