Sequence length:
Let's imagine that javascript Array has no built in method "length" in Array object. That's not a big problem, because we can get it with the help of reduce method:.js:
a = [10, 20, 30, 40] a.reduce(funciton(a, b){return ++a}, 0) // 4
.coffee:
a = [1, 2, 3, 4] a.reduce ((a, b) -> ++a), 0 # 4
The example above may be not so useful in a real world programming - but shows the key concept of how reduce function is working. It iterates through all elements in the sequence, the result of each iteration will be passed to the next iteration as the first argument and with the next sequence element as the second argument.
Let's take more complex example where we have a list of users, and we want to count how many of them has name - "user1" and how many of them are at the age of 19
.js
var reducer, users; // Let's create some simple array with users users = [ {"name": "user1", "age": 19}, {"name": "user2", "age": 20}, {"name": "user1", "age": 20} ]; reducer = function(a, b) { // setting default count values if aren't set yet a.user1_names_count || (a.user1_names_count = 0); a.age19_count || (a.age19_count = 0); // modifying returned value accordingly to our conditions if (b.name === "user1") { a.user1_names_count += 1; } if (b.age === 19) { a.age19_count += 1; } return a; }; users.reduce(reducer, {}) // {"user1_names_count":2,"age19_count":1} // so we have 2 users with name user1 and 1 user with age of 19
.coffee
users = [ {"name": "user1", "age": 19} {"name": "user2", "age": 20} {"name": "user1", "age": 20} ] reducer = (a, b) -> a.user1_names_count or= 0 a.age19_count or=0 (a.user1_names_count += 1) if b.name is "user1" (a.age19_count += 1) if b.age is 19 a users.reduce reducer, {} # will produce {"user1_names_count":2,"age19_count":1}
Array Sum
To take advantage of the reduce method let's try to calculate the sum of the array elements:
.js
a = [1, 2, 3, 4] a.reduce(function(a, b){return a + b}) // will produce 10
.coffee
a = [1, 2, 3, 4] a.reduce (a, b) -> a + b # will produce 10
And one of the most significant feature of reduce function - that if we want elements multiplication instead of addition - we just need to modify the reduce function to - something like this "function(a, b){return a * b}". And thats it. Combining map, reduce, filter methods provides us extremely powerful and flexible way of working with collections data.
Array reverse
We can get reversed array easily with the help of the reduce func:.js:
[1, 2, 3, 4].reduce(function (a, b){return [b].concat(a)}) // [4, 3, 2, 1].coffee:
[1, 2, 3, 4].reduce (a, b) -> [b].concat a # [4, 3, 2, 1]
Any
Let's imagine we want to know if there is one true element in the bool sequence:
.js:
l1 = [false, true, false, false] l2 = [false, false, false, false] l1.reduce(function(a, b){return a || b}) // true l2.reduce(function(a, b){return a || b}) // false
.coffee:
l1 = [false, true, false, false] l2 = [false, false, false, false] l1.reduce (a, b)-> a or b # true l2.reduce (a, b)-> a or b # false
All
If we will modify an example above a little, we may get function all, that tells us if all elements in sequence are true:
.js:
l1 = [true, true, true, true] l2 = [false, false, false, false] l1.reduce(function(a, b){return a && b}) // true l2.reduce(function(a, b){return a && b}) // false
.coffee:
l1 = [true, true, true, true] l2 = [false, false, false, false] l1.reduce (a, b)-> a and b # true l2.reduce (a, b)-> a and b # false
Unique values
Let's imagine we've got an array, and we need to filter only unique values from it. And the most interesting part of this - we may set some custom unique criteria in reduce function. Let's take a simple example where we have the list of integers and we want to get only the unique values from that list:.js:
unique_red = function(a, b){return a.indexOf(b)?a.concat(b):a} [2, 2, 1, 3].reduce(unique_red, []) // will produce [2, 1, 3]
.coffee:
unique_reducer = (a, b) -> unless b in a then a.concat b else a [2, 2, 1, 3].reduce unique_red, [] # will produce [2, 1, 3]
No comments:
Post a Comment