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 }
]
},
];
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);
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 }
]
]
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 }
]
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);
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);
Conclusão
Obrigado por ler! Espero que tenha entendido sobre a utilização de ambos os métodos.
Top comments (0)