What is map / reduce?

7

Map / Reduce is a very common concept in JavaScript and many other languages. What does it mean and how does it work in practice?

    
asked by anonymous 05.04.2017 / 02:50

3 answers

8

map (fn ( elemento ))

Used to perform a transformation on all items of a array . Similar to forEach() , with the difference that the map() callback should always return a value - and this value will always be added to the result array .

var arrOriginal = [1,2,3,4,5];

var arrFinal = arrOriginal.map(function (e) { return e * -1; });

console.log(arrFinal);

reduces (fn ( valorCorrent , elemento ), valorOriginal )

It is used to transverse a collection, accumulating and re-injecting the result for each interaction:

var vendedores = [
    { nome:'Adão', vendas:32 },
    { nome:'Bruno', vendas:23 },
    { nome:'Claudio', vendas:16 },
    { nome:'Dejair', vendas:7 },
    { nome:'Eduardo', vendas:4 },
    { nome:'Flavio', vendas:3 }
];

var totalVendas = vendedores.reduce(function(v, e) {
    return v + e.vendas;
}, 0);

console.log("Total de vendas: "+ totalVendas);

reduce() can also be used for structure transformations. The following example converts the list of objects to a single object with the name / sales property pair of the converted elements for property / value:

var vendedores = [
    { nome:'Adão', vendas:32 },
    { nome:'Bruno', vendas:23 },
    { nome:'Claudio', vendas:16 },
    { nome:'Dejair', vendas:7 },
    { nome:'Eduardo', vendas:4 },
    { nome:'Flavio', vendas:3 }
];

var totalVendas = vendedores.reduce(function(v, e) {
    v[e.nome] = e.vendas;
    return v;
}, {});

console.log(totalVendas);
    
05.04.2017 / 16:52
4

It has nothing to do with JS or NoSQL (it was in the original question). Of course, they use the technique, but associating them as if it's something fundamental does not make sense. It has become widespread in functional languages where the declarative form (say what to do and not how to do) imposes itself.

Normally it is a pair of functions, one that maps, that is, it takes a collection of data and processes each item possibly filtering some information, calculating some form or organizing in the expected form, and another that reduces the collection to a result based on the mapped items.

In general these functions are "how to do", and "what to do" is usually defined by lambdas .

Of course nothing prevents you from using the same technique without specific functions.

It is a technique that ends up resembling SQL that is a declarative language.

In JS the function map() applies an anonymous function receiving a parameter with each element that will be sent by the function. It is basically a for , which is even faster than map() . It's just a way to abstract the bond. The function reduce() uses an anonymous function that receives two parameters, one is the accumulator (which will result in a reduction) and the other one is the item to be accumulated (reduced).

Some languages have more specialized functions to help with performance. JS has some, such as filter() .

As far as I know there is no technique that can optimize the use of these functions together, as with LINQ , for example (which is not even as good as it could be). So it's just a waste of resources having to make at least 2 loops with the same data.

The advantage of the technique is when there is a very efficient framework and it can produce better results than typing the loop in the hand, which is quite difficult to achieve. In the case of JS it is only convenience (debatable). I would not call MapReduce what JS does, given its simplicity.

    
05.04.2017 / 03:19
1

Examples in C# with Linq :

Map, using the Select method:

var arrOriginal = new int[] { 1, 2, 3, 4, 5 };  
var arrFinal = arrOriginal.Select(n => n * -1);

Map Example in .Net Fiddle.

Reduce, using Sum :

public class Vendedor
{
    public string Nome {get;set;}
    public int Vendas {get;set;}
}

var vendedores = new List<Vendedor>() { 
            new Vendedor { Nome = "Adão", Vendas = 32 },
            new Vendedor { Nome = "Bruno", Vendas = 23 },
            new Vendedor { Nome = "Claudio", Vendas = 16 },
            new Vendedor { Nome = "Dejair", Vendas = 7 },
            new Vendedor { Nome = "Eduardo", Vendas = 4 },
            new Vendedor { Nome = "Flavio", Vendas = 3 }
        };

var totalVendas = vendedores.Sum(v => v.Vendas);

Reduce Example in .Net Fiddle.

    
05.04.2017 / 20:44