skip to Main Content

I have an array containing quantities of votes by gender and would like to convert the quantities to percentages by gender.

The array is as follows:

genderResults:  [
  { Qty: 7, Gender: 'Male', Answer: 'Badminton' },
  { Qty: 8, Gender: 'Female', Answer: 'Badminton' },
  { Qty: 2, Gender: 'Male', Answer: 'None of the above' },
  { Qty: 2, Gender: 'Female', Answer: 'None of the above' },
  { Qty: 3, Gender: 'Female', Answer: 'Rugby' },
  { Qty: 5, Gender: 'Male', Answer: 'Rugby' },
  { Qty: 4, Gender: 'Male', Answer: 'Soccer' },
  { Qty: 3, Gender: 'Female', Answer: 'Soccer' },
  { Qty: 21, Gender: 'Male', Answer: 'Squash' },
  { Qty: 16, Gender: 'Female', Answer: 'Squash' },
  { Qty: 1, Gender: 'Other', Answer: 'Squash' },
  { Qty: 18, Gender: 'Female', Answer: 'Tennis' },
  { Qty: 12, Gender: 'Male', Answer: 'Tennis' }
]

The required result would be like:

genderResults:  [
  { Percentage: 47, Gender: 'Male', Answer: 'Badminton' },
  { Percentage: 53, Gender: 'Female', Answer: 'Badminton' },
  { Percentage: 50, Gender: 'Male', Answer: 'None of the above' },
  { Percentage: 50: Gender: 'Female', Answer: 'None of the above' },
  { Percentage: 37, Gender: 'Male', Answer: 'Rugby' },
  { Percentage: 63: Gender: 'Female', Answer: 'Rugby' },
  ...
]

I’ve tried a forEach loop and array.map but can’t figure out how to group the results?

4

Answers


  1. Chosen as BEST ANSWER

    Thanks @nashit-shayan - modified your code to get what I was looking for.

    const genderPercent = genderResults.map(res =>{
        return {Gender: res.Gender, Answer: res.Answer, Percentage: Math.round((res.Qty / getCount(res.Answer)) * 100) }
    });
    
    function getCount(answer){
        return genderResults.reduce((sum, item)=>{
        if(answer){
            if(item.Answer == answer){
            sum+= item.Qty;
        }
        }
        else{
            sum+= item.Qty;
        }
        return sum
    },0)
    }
    console.log(genderPercent)
    

  2. const totalQtyByGender = {};
    const totalQtyByAnswer = {};
    
    // Calculate total quantity by gender and answer
    genderResults.forEach(result => {
      const { Qty, Gender, Answer } = result;
      totalQtyByGender[Gender] = (totalQtyByGender[Gender] || 0) + Qty;
      totalQtyByAnswer[Answer] = (totalQtyByAnswer[Answer] || 0) + Qty;
    });
    
    // Calculate the percentage
    const output = genderResults.map(result => {
      const { Qty, Gender, Answer } = result;
      const percentage = (Qty / totalQtyByGender[Gender]) * 100;
      return { Percentage: percentage, Gender, Answer };
    });
    
    console.log(output);
    

    We can also do it with the help of reduce method but you tried it with the help of foreach method so here it is.

    Login or Signup to reply.
  3. It can be cleaned up a bit, but I think this will fulfill your requirements. I haven’t considered any edge cases, btw.

    const genderResults = [
      { Qty: 7, Gender: 'Male', Answer: 'Badminton' },
      { Qty: 8, Gender: 'Female', Answer: 'Badminton' },
      { Qty: 2, Gender: 'Male', Answer: 'None of the above' },
      { Qty: 2, Gender: 'Female', Answer: 'None of the above' },
      { Qty: 3, Gender: 'Female', Answer: 'Rugby' },
      { Qty: 5, Gender: 'Male', Answer: 'Rugby' },
      { Qty: 4, Gender: 'Male', Answer: 'Soccer' },
      { Qty: 3, Gender: 'Female', Answer: 'Soccer' },
      { Qty: 21, Gender: 'Male', Answer: 'Squash' },
      { Qty: 16, Gender: 'Female', Answer: 'Squash' },
      { Qty: 1, Gender: 'Other', Answer: 'Squash' },
      { Qty: 18, Gender: 'Female', Answer: 'Tennis' },
      { Qty: 12, Gender: 'Male', Answer: 'Tennis' }
    ];
    
    const totalCount = getCount();
    
    const genderPercent = genderResults.map(res =>{
        return {Gender: res.Gender, Answer: res.Answer, Percentage: Math.round((res.Qty / totalCount) * 100) }
    });
    
    // const maleCount = getCount('Male');
    // const femaleCount = getCount('Female');
    
    function getCount(gender){
        return genderResults.reduce((sum, item)=>{
        if(gender){
            if(item.Gender == gender){
            sum+= item.Qty;
        }
        }
        else{
             sum+= item.Qty;
        }
        return sum
    },0)
    }
    console.log(totalCount, genderPercent)
    

    Update:

    Here you go 🙂

    const categoryCount = genderResults.reduce((res, item)=>{
            if(res[item.Answer]){
                res[item.Answer]+= item.Qty
            }
            else{
                res[item.Answer] = item.Qty
            }
            return res;
    }, {})
    
    console.log({categoryCount})
    const genderPercent = genderResults.map(res =>{
        return {
            Gender: res.Gender, 
            Answer: res.Answer, 
            Percentage: Math.round((res.Qty / categoryCount[res.Answer]) * 100) 
        }
    });
    
    
    console.log(genderPercent)
    
    
    Login or Signup to reply.
  4. We can use Array.reduce() to group the genderResults array by
    Answer.

    We’ll also keep track of the total quantity for each answer and use this to calculate a percentages array for each one.

    Once we have this grouped value, we can use Object.values
    and Array.flatMap to get the final result.

    const genderResults =  [ { Qty: 7, Gender: 'Male', Answer: 'Badminton' }, { Qty: 8, Gender: 'Female', Answer: 'Badminton' }, { Qty: 2, Gender: 'Male', Answer: 'None of the above' }, { Qty: 2, Gender: 'Female', Answer: 'None of the above' }, { Qty: 3, Gender: 'Female', Answer: 'Rugby' }, { Qty: 5, Gender: 'Male', Answer: 'Rugby' }, { Qty: 4, Gender: 'Male', Answer: 'Soccer' }, { Qty: 3, Gender: 'Female', Answer: 'Soccer' }, { Qty: 21, Gender: 'Male', Answer: 'Squash' }, { Qty: 16, Gender: 'Female', Answer: 'Squash' }, { Qty: 1, Gender: 'Other', Answer: 'Squash' }, { Qty: 18, Gender: 'Female', Answer: 'Tennis' }, { Qty: 12, Gender: 'Male', Answer: 'Tennis' } ]
    
    const grouped = genderResults.reduce((acc, row) => { 
        const key = row.Answer;
        acc[key] = acc[key] || { totalQty: 0, entries: [] };
        acc[key].entries.push(row);
        acc[key].totalQty += row.Qty;
        acc[key].percentages = acc[key].entries.map(entry => { 
            return { 
                Percentage: Math.round(100 * entry.Qty / acc[key].totalQty),
                Gender: entry.Gender,
                Answer: entry.Answer
            }
        })
        return acc;
    }, {})
    
    const result = Object.values(grouped).flatMap(obj => obj.percentages)
    console.log('Result:')
    result.forEach(r => console.log(JSON.stringify(r)))
    .as-console-wrapper { max-height: 100% !important; }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search