MapReduce com javascript

Hoje em dia, falamos muito em mineração de dados e como fazer isso de forma sofisticada. Como uma estrategia, podemos fazer algoritmos que compilem isso do lado client e não server-side, dessa maneira seria como compilar uma enorme quantidade de dados de forma distribuída, aliviando assim o stress no servidores.

Hoje vamos aprender a fazer isso com duas funções javascript, uma chamada MAP e outra REDUCE.

Na pratica, seria como se separássemos todos os dados em conjuntos ordenados e depois fazemos pequenas somas, dessa maneria podemos ter dois tipos resultados, um único valor se todos os elementos forem do mesmo tipo ou um vetor com valores separados se forem de tipos diferentes.

Primeiro vamos fazer um Array com os dados para minerar:

var dadosSoma = [1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3];

Utilizando o método MAP

O objeto Array tem alguns métodos bem interessante, incluindo o MAP, ok, mas como ele funciona?

Quando chamamos esse método, ele recebe dois parâmetros.

Callback: uma função de retorno que vai ser aplicada em todos os elementos do array, deve-se retornar sempre um elemento do mesmo tipo para ocupar o lugar dentro do conjunto.

ThisArg: opcional, geralmente para saber qual a posição do lindice ou algum objeto que precise ter interação com todos os elementos.

Depois de entender esses parâmetros o nosso código fica dessa maneira:

var dadosSoma = [1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3];

var mapSoma = dadosSoma.map(functionMapCallback);

Criando a functionMapCallback

Como primeiro parâmetro temos o elemento da posição atual, depois de manipular ela, fazemos o retorno substituindo a posição desse elemento por esse novo valor dentro do conjunto gerado pelo o map, a função implementada fica assim:

var functionMapCallback = function(elemento){ return elemento = elemento *2; /* multiplicando todos os elementos do array por 2 */ };

Usando o método reduce:

O método reduce recebe dois paramentos,a função de callback e qual o valor de inicio, sendo o segundo parâmetro opcional.

Com esse novo método o nosso código fica dessa maneira:

var dadosSoma = [1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3];

var functionMapCallback = function(elemento){ return elemento = elemento *2; /* multiplicando todos os elementos do array por 2 */ };

var mapSoma = dadosSoma.map(functionMapCallback);

var reduceSoma = mapSoma.reduce(functionReduceCallback);
Criando a functionReduceCallback:

Quando o método reduce, faz a chamada da função, ele passa dois parâmetros o valor anterior e o atual dentro de um mesmo conjunto. Como estamos trabalhando com uma soma de valores, a função final fica assim:

var functionReduceCallback = function(anterior,atual){ return anterior+atual /*somando os elementos do conjunto e retornando o valor que substitui esses dois elementos */}

E agora o nosso código fica dessa maneira:

var dadosSoma = [1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3];

var functionReduceCallback = function(anterior,atual){ return anterior+atual /*somando os elementos do conjunto e retornando o valor que substitui esses dois elementos */}

var functionMapCallback = function(elemento){ return elemento = elemento *2; /* multiplicando todos os elementos do array por 2 */ };

var mapSoma = dadosSoma.map(functionMapCallback);

var reduceSoma = mapSoma.reduce(functionReduceCallback);
E como resultado final o valor da variável dadosSoma se torna 132.

Refinamento de código:

var dadosSoma = [1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3,1, 2, 3];

dadosSoma =dadosSoma.map(function(anterior,atual){return elemento = elemento *2; }).reduce(function(elemento){return anterior+atual; );

alert(dadosSoma); //exibindo o valor do resultado
Esse tipo de pensando, em dividir grandes quantidades de dados em conjuntos, economiza muito processamento e torna o código mais refinado para outros programadores. Fazer esse tipo de implementação no lado do client, entra no conceito de sistema distribuídos, aonde você divide a compilação dos dados pelo o numero de acessos e cada client fica responsável por compilar os seus dados, ao invés do servidor compilar milhões de usuários juntos.

Bookmark the permalink.