Map Filter Reduce
Map-reduce is a silver bullet strategy created for processing data.
As a lover of functional programming I like to use map
, filter
, and reduce
for data processing.
Let's imagine that we have got a list of students.
This example is using seeded random!
var students = [];
var rand = Math.random.seeded.rand;
rand.setSeed('students example');
for(var i = 0; i < 1000; i++)
students.push({
name: 'Some name',
sex: rand(['male', 'female']),
grade: rand(1, 11),
letter: rand(['A', 'B', 'C', 'D']),
weight: rand(20, 55),
favorite: rand([
'Math', 'Physics',
'Grammar', 'Literature',
'Informatics', 'Chemistry'
])
});
// set students age
students.forEach(student => student.age = student.grade + 7 + (rand(-1, 1)|0));
Filter
… and we want to count the amount of females in the 9B class …
var count = students
.filter( student => student.sex === 'female')
.filter( student => student.grade === 9)
.filter( student => student.letter === 'B')
.length // 15
Reduce
… and, we want to know their average age …
var matched = students
.filter( student => student.sex === 'female')
.filter( student => student.grade === 9)
.filter( student => student.letter === 'B');
var averageAge = matched
.reduce( (accumulator, student) => accumulator += student.age, 0 )
/ matched.length;
Map
Map is a one-to-one mapping where each element of an array is processed through a function. The result is formed from the outputs of the function.
The classical demonstration of map is multiplying an array
[0,1,2,3,4,5].map( x => x*2 ) // [0,2,4,6,8,10]
But I want to show a more usable example. We have ten points, and we want to highlight the closest one.
var background = 0x113333
var points = [];
for(var i = 0; i < 20; i++)
points.push(new Point(rand(w), rand(h)));
update = function(dt, t){
rect(0,0,w,h, background)
for(var i = 0; i < 20; i++) {
var point = points[i];
circle( point.x, point.y, 1, 0x00ffff );
}
// Spice each point with distance to the mouse and then just sort them
var closestPoints = points
.map(point => ({point, distance: point.distance(mouse)}))
.sort((p1, p2) => p1.distance - p2.distance)
.map(({point}) => point);
var closestPoint = closestPoints[0];
var currentStepColor = color(
sin(t)*127+128,
sin(t*1.4+21)*127+128,
sin(t*2.4+5)*127+128
);
/*for(var i = 0; i < 4; i++)
arrow(mouse, closestPoints[i], lighter(background, 1+i*0.2));*/
arrow(mouse, closestPoint, currentStepColor);
circle( closestPoint.x, closestPoint.y, 3+sin(t*3), 0x77ff00 );
}
move = function(){}