'How do I organize an Array of objects according to the sum of its attributes?

I’m developing the backEnd part for a selling app in which I have 2 Array of Objects, one got the sellers' name, and the other has the monthly sales. I was told by my superiors to order the Array of names from the one that made the most sales to the one that made the least ( from highest to lowest ) using the data from the array which contains the sales, basically making a summation of the key => quantity. I’m not sure how to do it, I tried to use a Reduce method with the sales of each seller but I can’t think how to compare them to reorganize the Array. The code is:

const sellers= [{id:1,name: 'juan', age: 23},{id:2,name: 'adrian', age: 32},{id:3,name: 'apolo', age: 45}];

const sales= [{equipo: 'frances', sellerId: 2, quantity: 234},{equipo: 'italiano', sellerId: 3, quantity: 24},{equipo: 'polaco', sellerId: 1, quantity: 534},{equipo: 'frances', sellerId: 2, quantity: 1234},{equipo: 'frances', sellerId: 3, quantity: 2342}];

This is what I have already tried:

const bestSellers= () => {
  sales.reduce((sum, value) => ( value.sellerId == 1 ? sum + value.area : sum), 0); }

The final result should look like this:

const sellers= [{id:3,name: 'apolo', age: 45},{id:2,name: 'adrian', age: 32},{id:1,name: 'juan', age: 23}]


Solution 1:[1]

First, reduce the sales array to the sum of quantity for each seller, sort this list and then map to the respective seller from the sellers array.

const sellers= [{id:1,name: 'juan', age: 23},{id:2,name: 'adrian', age: 32},{id:3,name: 'apolo', age: 45}];

const sales= [{equipo: 'frances', sellerId: 2, quantity: 234},{equipo: 'italiano', sellerId: 3, quantity: 24},{equipo: 'polaco', sellerId: 1, quantity: 534},{equipo: 'frances', sellerId: 2, quantity: 1234},{equipo: 'frances', sellerId: 3, quantity: 2342}];

const bestSellers = (sellers, sales) => {
  let res = sales.reduce((result, sale) => {
    // Check if seller is already added in result
    const obj = result.find(s => s.sellerId === sale.sellerId);
    if (obj) {
      // If seller already added then increase it's quantity
        obj.quantity += sale.quantity;
    } else {
      // If seller not added, add seller in result
        result.push({ sellerId: sale.sellerId, quantity: sale.quantity });
    }
    return result;
  }, []);
    
  // Sort result by quantity in decreasing order 
  res.sort((a,b) => b.quantity - a.quantity);
  
  // Map each sale to the seller
  res = res.map(s => sellers.find(seller => seller.id === s.sellerId));
    
  return res;
}

const result = bestSellers(sellers, sales);
console.log(result);

Solution 2:[2]

you can do that:

const
  sellers = 
    [ { id: 1, name: 'juan',   age: 23 } 
    , { id: 2, name: 'adrian', age: 32 } 
    , { id: 3, name: 'apolo',  age: 45 } 
    ] 
, sales = 
    [ { equipo: 'frances',  sellerId: 2, quantity:  234 } 
    , { equipo: 'italiano', sellerId: 3, quantity:   24 } 
    , { equipo: 'polaco',   sellerId: 1, quantity:  534 } 
    , { equipo: 'frances',  sellerId: 2, quantity: 1234 } 
    , { equipo: 'frances',  sellerId: 3, quantity: 2342 } 
    ];


sellers.forEach( ({id},i,all) => // add a sum attribute 
  {
  all[i].sum = sales
                .filter(({sellerId})=>sellerId===id)
                .reduce((sum,{quantity})=>sum+quantity,0)
  });

sellers
  .sort( (a,b) => b.sum - a.sum)                 
  .forEach((seller,i,all) => delete seller.sum ) // remove the sum

console.log( sellers )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

or:

const
  sellers = 
    [ { id: 1, name: 'juan',   age: 23 } 
    , { id: 2, name: 'adrian', age: 32 } 
    , { id: 3, name: 'apolo',  age: 45 } 
    ] 
, sales = 
    [ { equipo: 'frances',  sellerId: 2, quantity:  234 } 
    , { equipo: 'italiano', sellerId: 3, quantity:   24 } 
    , { equipo: 'polaco',   sellerId: 1, quantity:  534 } 
    , { equipo: 'frances',  sellerId: 2, quantity: 1234 } 
    , { equipo: 'frances',  sellerId: 3, quantity: 2342 } 
    ] 

// compute all the sum in a new Sums object:
const Sums = sales.reduce((sum,{sellerId : id, quantity}) =>
  ( sum[id] ??= 0, sum[id] += quantity , sum ), {} )

sellers .sort( (a,b) => Sums[b.id] - Sums[a.id])

console.log( sellers )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

Solution 3:[3]

You can do:

const sellers = [{ id: 1, name: 'juan', age: 23 },{ id: 2, name: 'adrian', age: 32 },{ id: 3, name: 'apolo', age: 45 },]
const sales = [{ equipo: 'frances', sellerId: 2, quantity: 234 },{ equipo: 'italiano', sellerId: 3, quantity: 24 },{ equipo: 'polaco', sellerId: 1, quantity: 534 },{ equipo: 'frances', sellerId: 2, quantity: 1234 },{ equipo: 'frances', sellerId: 3, quantity: 2342 },]

const salesHash = sales.reduce((a, { sellerId, quantity }) => 
  (a[sellerId] = (a[sellerId] || 0) + quantity, a), {})

const result = sellers.sort((a, b) => 
  salesHash[b.id] - salesHash[a.id])

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PR7
Solution 2
Solution 3 Yosvel Quintero Arguelles