DEV Community

Cover image for Map x flatMap, entendendo a diferença na prática
Ivan Trindade
Ivan Trindade

Posted on

Map x flatMap, entendendo a diferença na prática

Neste artigo veremos a diferença entre as funções map() e flatMap(), inclusive como implementar esta última para que possamos escrever um código mais elegante. Vamos ao problema.

const notas = [
    {
        data: '2017-10-31',
        itens: [
            { conta: '2143', valor: 200 },
            { conta: '2111', valor: 500 }
        ]
    },
    {
        data: '2017-07-12',
        itens: [
            { conta: '2222', valor: 120 },
            { conta: '2143', valor: 280 }
        ]
    }, 
    {
        data: '2017-02-02',
        itens: [
            { conta: '2143', valor: 110 },
            { conta: '7777', valor: 390 }
        ]
    },     
];
Enter fullscreen mode Exit fullscreen mode

Precisamos totalizar o valor de todos os itens com a conta 2143. E agora?

Tentando solucionar com map()

Podemos apelar para a função map(), aquela que permite aplicar uma transformação em cada elemento do array resultando em um novo array. Nesse sentido, queremos transformar cada nota iterada em um array de itens que possamos realizar filter e reduce para filtrar e totalizar respectivamente:

// não funciona como esperado! O resultado será 0!
const totalDeUmaConta = 
    notas.map(nota => nota.itens)
        .filter(item => item.conta == '2143')
        .reduce((total, item) => total + item.valor, 0);

console.log(totalDeUmaConta);      
Enter fullscreen mode Exit fullscreen mode

Infelizmente o código acima não funciona, porque o resultado de map() será multidimensional, ou seja, um array de arrays:

// resultado do map
[
    [
        { conta: '2143', valor: 200 },
        { conta: '2111', valor: 500 }
    ],
    [
        { conta: '2222', valor: 120 },
        { conta: '2143', valor: 280 }
    ],
     [
        { conta: '2143', valor: 110 },
        { conta: '7777', valor: 390 }
    ]
]
Enter fullscreen mode Exit fullscreen mode

Para que a função filter() funcione como esperado, o array deveria ter uma estrutura inidimensional:

// estrutura esperada por filter
[
    { conta: '2143', valor: 200 },
    { conta: '2111', valor: 500 },
    { conta: '2222', valor: 120 },
    { conta: '2143', valor: 280 },
    { conta: '2143', valor: 110 },
    { conta: '7777', valor: 390 }   
]
Enter fullscreen mode Exit fullscreen mode

Uma solução é abdicarmos do map e utilizarmos reduce para achatarmos o array multidimensional em um array de uma dimensão apenas. Vejamos:

// Agora sim!

totalDeUmaConta = notas
    .reduce((array, nota) => array.concat(nota.itens), [])
    .filter(item => item.conta == '2143')
    .reduce((total, item) => total + item.valor, 0);
Enter fullscreen mode Exit fullscreen mode

Se o leitor compreendeu o motivo pelo qual o primeiro reduce foi necessário, já sabe a finalidade do flatMap, até porque este reduce está exercendo sua função.

Uma solução com flatMap()

A função flatMap() realiza um map de uma função sobre uma coleção de dados, porém achatando o resultado final em um nível, isto é, retornando um array de uma dimensão apenas.

totalDeUmaConta = notas
    .flatMap(nota => nota.itens)
    .filter(item => item.conta === '2143')
    .reduce((total, item) => total + item.valor, 0);

console.log(totalDeUmaConta);
Enter fullscreen mode Exit fullscreen mode

Conclusão

Obrigado por ler! Espero que tenha entendido sobre a utilização de ambos os métodos.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay