Calculate 2 different array element totals according to the value of another property

Asked

Viewed 64 times

2

My goal is to separate the sum of only women’s wages into one filter + reduce and the sum of men’s wages in another using also filter + reduce.

The console.log(salarioMulher) in the last row is making the total sum of wages, could help me make the specific female and male sum?

const funcionarios = [
    { nome: "Joany", salario: 4500, sexo: "F"},
    { nome: 'Junior', salario: 4500, sexo: 'M'},
    { nome: 'Julio', salario: 3500, sexo: 'M'},
    { nome: 'Grazy', salario: 3000, sexo: 'F'},
    { nome: 'Rafael', salario: 6000, sexo: 'M'},
    { nome: 'Artur', salario: 7800, sexo: 'M'},
    { nome: 'Ana', salario: 3300, sexo: 'F'},
    { nome: 'Bianca', salario: 12500, sexo: 'F'},
    { nome: 'José', salario: 8400, sexo: 'M'},
    { nome: 'Maria', salario: 5500, sexo: 'F'}   
]
 
JSON.stringify(funcionarios)
 
const apenasMulher = a => a.sexo === 'F' 
const apenasHomem = a => a.sexo === 'M'
 
 
const somaSalario = sal => sal.salario
const totalSalario = (sal, salAtual) => {
return sal + salAtual   
}
 
const arraySalario = funcionarios.map(somaSalario)
const salarioMulher = arraySalario.reduce(totalSalario)
 
 
const func = funcionarios.filter(apenasMulher)
console.log(func)
console.log(salarioMulher)

1 answer

3


You have already created the functions to filter men and women, another to map each employee with their respective salary and another to calculate the sum of the elements of an array. Just needed to match them in the right order:

const funcionarios = [
    { nome: "Joany", salario: 4500, sexo: "F"},
    { nome: 'Junior', salario: 4500, sexo: 'M'},
    { nome: 'Julio', salario: 3500, sexo: 'M'},
    { nome: 'Grazy', salario: 3000, sexo: 'F'},
    { nome: 'Rafael', salario: 6000, sexo: 'M'},
    { nome: 'Artur', salario: 7800, sexo: 'M'},
    { nome: 'Ana', salario: 3300, sexo: 'F'},
    { nome: 'Bianca', salario: 12500, sexo: 'F'},
    { nome: 'José', salario: 8400, sexo: 'M'},
    { nome: 'Maria', salario: 5500, sexo: 'F'}   
];

const apenasMulher = a => a.sexo === 'F';
const apenasHomem = a => a.sexo === 'M';

// mudei o nome para "obtemSalario" pois "somaSalario" não é bem o que ela faz
const obtemSalario = sal => sal.salario;
const totalSalario = (sal, salAtual) => {
    return sal + salAtual;
};

let totalMulheres = funcionarios.filter(apenasMulher).map(obtemSalario).reduce(totalSalario);
let totalHomens = funcionarios.filter(apenasHomem).map(obtemSalario).reduce(totalSalario);
console.log(totalMulheres);
console.log(totalHomens);

That is, first you filter by the desired criterion (filter to have only men, or only women), then maps them to their salaries (map), and only then do you add up everything (reduce).

In your code you made funcionarios.map(somaSalario), that is, took the salaries of all employees, and then summed up everything (missed the filter to filter only women). In fact you called the filter afterward, but there is no point because the total had already been calculated.

Also note that I changed the function name somaSalario for obtemSalario, because she wasn’t adding anything up, she was just serving to map each employee to their respective salary. It may seem like a silly detail, but give names better help when programming.

I also put a semicolon at the end of the lines. It may sound "fresh," and I know that Javascript "accepts" the semicolon code and "works," but it avoids some bizarre situations that can occur if you don’t use them, like that one and that one (see more about this here).


Alternatives

Just for the record, there are other alternatives, some even eliminating the need for filter and/or the map:

function somar(dados, campo, sexo) {
    // usando filter, map e reduce
    //return dados.filter(e => e.sexo === sexo).map(e => e[campo]).reduce((a, b) => a + b);
    // ou sem o map
    //return dados.filter(e => e.sexo === sexo).reduce((a, b) => a + b[campo], 0);
    // ou só com reduce
    return dados.reduce((a, b) => a + (b.sexo === sexo ? b[campo] : 0), 0);
}

console.log(somar(funcionarios, 'salario', 'F')); // totalMulheres
console.log(somar(funcionarios, 'salario', 'M')); // totalHomens

Or even, returning an object with both totals:

let { totalHomens, totalMulheres } = funcionarios.reduce(function (a, b) {
    if (b.sexo === 'M') {
        a.totalHomens += b.salario;
    } else if (b.sexo === 'F') {
        a.totalMulheres += b.salario;
    }
    return a;
}, { totalHomens: 0, totalMulheres: 0 });

console.log(totalMulheres);
console.log(totalHomens);

This last one in particular I already consider an exaggeration (and a certain abuse of reduce), but it remains as a curiosity...


Without filter/map/reduce

But did he need all this? Every call filter and map traverse the array elements and return another array, and reduce makes several calls from callback totalSalario to make a simple sum. That is, not only are you going through the same elements over and over again, you are creating various intermediate structures for nothing.

I find it much simpler to make just one for:

const funcionarios = [
    { nome: "Joany", salario: 4500, sexo: "F"},
    { nome: 'Junior', salario: 4500, sexo: 'M'},
    { nome: 'Julio', salario: 3500, sexo: 'M'},
    { nome: 'Grazy', salario: 3000, sexo: 'F'},
    { nome: 'Rafael', salario: 6000, sexo: 'M'},
    { nome: 'Artur', salario: 7800, sexo: 'M'},
    { nome: 'Ana', salario: 3300, sexo: 'F'},
    { nome: 'Bianca', salario: 12500, sexo: 'F'},
    { nome: 'José', salario: 8400, sexo: 'M'},
    { nome: 'Maria', salario: 5500, sexo: 'F'}   
];

let totalHomens = 0;
let totalMulheres = 0;
for (const func of funcionarios) {
    switch(func.sexo) {
        case 'M':
            totalHomens += func.salario;
            break;
        case 'F':
            totalMulheres += func.salario;
            break;
    }
}
console.log(totalMulheres);
console.log(totalHomens);

  • thank you very much, and thank you also for giving other alternatives, I do computer science but I have not seen programming right yet, to no 2 periodo e a faculdade ta parada, I’m taking the opportunity to take a course, I asked for help with the specified functions of the array because I had a little doubt in the operation of the map and reduce, so it was just a typo at the end, thanks for the alternatives off the part using loop :)

  • @Juniorjarismar If the answer solved your problem, you can accept it, see here how and why to do it. It is not mandatory, but it is a good practice of the site, to indicate to future visitors that it solved the problem. Don’t forget that you can also vote in response, if it has found it useful.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.