2

I have an array like this :

[
    {
        "orderId": 1,
        "orderDate": "2021-04-28T08:20:58Z",
        "status": "Confirmed",
        "sellerName": "Chris Gilmour",
        "revenue": 2316.49
    },
    {
        "orderId": 2,
        "orderDate": "2020-12-19T12:30:18Z",
        "status": "Confirmed",
        "sellerName": "Alanna Sumner",
        "revenue": 2928.88
    },
    {
        "orderId": 4,
        "orderDate": "2020-12-24T08:00:09Z",
        "status": "Confirmed",
        "sellerName": "Beth North",
        "revenue": 1550.19
    },
    {
        "orderId": 5,
        "orderDate": "2021-06-06T04:40:48Z",
        "status": "Confirmed",
        "sellerName": "Laura Ponce",
        "revenue": 35.5
    },
    {
        "orderId": 8,
        "orderDate": "2021-08-27T05:13:40Z",
        "status": "Canceled",
        "sellerName": "Blade Newman",
        "revenue": 2957.29
    },
    {
        "orderId": 9,
        "orderDate": "2020-12-26T08:07:57Z",
        "status": "Confirmed",
        "sellerName": "Alanna Sumner",
        "revenue": 2164.75
    },
    {
        "orderId": 10,
        "orderDate": "2021-04-23T18:44:19Z",
        "status": "Confirmed",
        "sellerName": "Blade Newman",
        "revenue": 2287.55
    }
]

I want the new Array to be :

[ 
    {
        "sellerName": "Blade Newman",
        "totalRevenue": 5244.84
    },
    {
        "sellerName": "Alanna Sumner",
        "totalRevenue": 5093.63
    },
    { 
        "sellerName": "Chris Gilmour",
        "totalRevenue" : 2316.49
    },
    {
        "sellerName": "Beth North",
        "totalRevenue": 1550.19
    }

]

So I want the array to be grouped by sellerName, the amount sold summed up and ordered By sellers with the most total sales.

I tried to solve this by using forEachs and reduces but I failed, if anyone can help me that would be great.

Thanks in advance.

Plínio Helpa
  • 137
  • 1
  • 9
  • 1
    1. Construct the hash `{ "Chris Gilmour"=>2316.49, "Alanna Sumner"=>5093.63, "Beth North"=>1550.19, "Laura Ponce"=>35.5, "Blade Newman" => 5244.84 }`. 2. Convert the hash to the array `[["Chris Gilmour", 2316.49], ["Alanna Sumner", 5093.63], ["Beth North", 1550.19], ["Laura Ponce",35.5], ["Blade Newman", 5244.84]]`. 3. Sort the array by decreasing second element of each two-element array. Map each element of the sorted array to a hash with keys `"sellerName"` and `"totalRevenue"`. – Cary Swoveland Apr 13 '22 at 01:48

7 Answers7

3

As described by @CarySwoveland in the comments, you can accumulate revenue for each seller in an object, convert the object entries to an array to sort, and then generate a new object based on the sorted values:

const sales = [{
    "orderId": 1,
    "orderDate": "2021-04-28T08:20:58Z",
    "status": "Confirmed",
    "sellerName": "Chris Gilmour",
    "revenue": 2316.49
  },
  {
    "orderId": 2,
    "orderDate": "2020-12-19T12:30:18Z",
    "status": "Confirmed",
    "sellerName": "Alanna Sumner",
    "revenue": 2928.88
  },
  {
    "orderId": 4,
    "orderDate": "2020-12-24T08:00:09Z",
    "status": "Confirmed",
    "sellerName": "Beth North",
    "revenue": 1550.19
  },
  {
    "orderId": 5,
    "orderDate": "2021-06-06T04:40:48Z",
    "status": "Confirmed",
    "sellerName": "Laura Ponce",
    "revenue": 35.5
  },
  {
    "orderId": 8,
    "orderDate": "2021-08-27T05:13:40Z",
    "status": "Canceled",
    "sellerName": "Blade Newman",
    "revenue": 2957.29
  },
  {
    "orderId": 9,
    "orderDate": "2020-12-26T08:07:57Z",
    "status": "Confirmed",
    "sellerName": "Alanna Sumner",
    "revenue": 2164.75
  },
  {
    "orderId": 10,
    "orderDate": "2021-04-23T18:44:19Z",
    "status": "Confirmed",
    "sellerName": "Blade Newman",
    "revenue": 2287.55
  }
];

let totalsales = sales.reduce((acc, {
  sellerName,
  revenue
}) => {
  acc[sellerName] = (acc[sellerName] || 0) + revenue;
  return acc;
}, {});

totalsales = Object.entries(totalsales)
.sort((a, b) => b[1] - a[1])
.map((v) => ({ sellerName: v[0], totalRevenue: v[1] }))

console.log(totalsales)
Nick
  • 138,499
  • 22
  • 57
  • 95
1

You can try this:

    const newArray=[];
    for (var order of orders) {
        var index = newArray.findIndex((a)=>a.sellerName==order.sellerName);
        if (index>-1){
            newArray[index].totalRevenue+=order.revenue;
        } else {
            newArray.push({
                sellerName: order.sellerName,
                totalRevenue: order.revenue
           }) 
       }
   } 
   newArray.sort((a,b)=>b.totalRevenue-a.totalRevenue);
Tanay
  • 871
  • 1
  • 6
  • 12
1

Use a simple for loop to make a hash of revenue by seller name (this is more readable than reduce).

const revenueByName = {};
for (const {sellerName, revenue} of data) {
    revenueByName[sellerName] = (revenueByName[sellerName] ?? 0) + revenue;
}
const result = Object.entries(revenueByName)
    .map(([sellerName, totalRevenue]) => ({sellerName, totalRevenue}))
    .sort((a, b) => b.totalRevenue - a.totalRevenue);
Stuart
  • 9,597
  • 1
  • 21
  • 30
1

Same technique as in other answers, but folded into a single function:

const total = (sales) => 
  Object .entries (sales .reduce (
    (a, {sellerName: n, revenue}) => ({...a, [n] : (a[n] ?? 0) + revenue}), 
    {}
  )) .map (([sellerName, totalRevenue]) => ({sellerName, totalRevenue}))

const sales = [{orderId: 1, orderDate: "2021-04-28T08: 20: 58Z", status: "Confirmed", sellerName: "Chris Gilmour", revenue: 2316.49}, {orderId: 2, orderDate: "2020-12-19T12: 30: 18Z", status: "Confirmed", sellerName: "Alanna Sumner", revenue: 2928.88}, {orderId: 4, orderDate: "2020-12-24T08: 00: 09Z", status: "Confirmed", sellerName: "Beth North", revenue: 1550.19}, {orderId: 5, orderDate: "2021-06-06T04: 40: 48Z", status: "Confirmed", sellerName: "Laura Ponce", revenue: 35.5}, {orderId: 8, orderDate: "2021-08-27T05: 13: 40Z", status: "Canceled", sellerName: "Blade Newman", revenue: 2957.29}, {orderId: 9, orderDate: "2020-12-26T08: 07: 57Z", status: "Confirmed", sellerName: "Alanna Sumner", revenue: 2164.75}, {orderId: 10, orderDate: "2021-04-23T18: 44: 19Z", status: "Confirmed", sellerName: "Blade Newman", revenue: 2287.55}]

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

Using reduce, we get this intermediate format:

{
  "Chris Gilmour": 2316.49,
  "Alanna Sumner": 5093.63,
  "Beth North": 1550.19,
  "Laura Ponce": 35.5,
  "Blade Newman": 5244.84
}

Then Object .entries turns it into

[
  ["Chris Gilmour", 2316.49],
  ["Alanna Sumner", 5093.63],
  ["Beth North", 1550.19],
  ["Laura Ponce", 35.5],
  ["Blade Newman", 5244.84]
]

and the map call turns it into its final form.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • If you don't mind, I'd like to ask you to say a few words about codestyle that puts a space before the period. Does this style have a name? What is its advantages? – A1exandr Belan Apr 16 '22 at 10:57
  • @A1exandrBelan: I know of no name for it. I picked it up from another user here (who has since stopped doing it.) I simply find it more readable. I like the emphasis on the methods on their own, and the extra space feels luxurious.. – Scott Sauyet Apr 17 '22 at 02:18
0

//temp = given array
let result = temp.reduce((acc, curr) => {
    if (acc[curr.sellerName]) {
        acc[curr.sellerName] += curr.revenue;
    } else {
        acc[curr.sellerName] = curr.revenue;
    }
    return acc;
}, {});
// console.log(result, (a, b) => {
//     console.log
// });
result = Object.entries(result).map((value) => {
    return {
        sellerName: value[0],
        revenue: value[1],
    };
});

result = result.sort((a, b) => a["revenue"] - b["revenue"]);
console.log(result);
ace1234
  • 131
  • 7
0

You can combine map with grouping step together, and then just sort array

const orders=[{orderId:1,orderDate:"2021-04-28T08:20:58Z",status:"Confirmed",sellerName:"Chris Gilmour",revenue:2316.49},{orderId:2,orderDate:"2020-12-19T12:30:18Z",status:"Confirmed",sellerName:"Alanna Sumner",revenue:2928.88},{orderId:4,orderDate:"2020-12-24T08:00:09Z",status:"Confirmed",sellerName:"Beth North",revenue:1550.19},{orderId:5,orderDate:"2021-06-06T04:40:48Z",status:"Confirmed",sellerName:"Laura Ponce",revenue:35.5},{orderId:8,orderDate:"2021-08-27T05:13:40Z",status:"Canceled",sellerName:"Blade Newman",revenue:2957.29},{orderId:9,orderDate:"2020-12-26T08:07:57Z",status:"Confirmed",sellerName:"Alanna Sumner",revenue:2164.75},{orderId:10,orderDate:"2021-04-23T18:44:19Z",status:"Confirmed",sellerName:"Blade Newman",revenue:2287.55}];

const result = Object.values(orders.reduce((acc, { sellerName, revenue }) => {
    acc[sellerName] ??= { sellerName, totalRevenue: 0 };
    acc[sellerName].totalRevenue += revenue;
    return acc;
}, {}))
.sort(({ totalRevenue: a }, { totalRevenue: b }) => b - a);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A1exandr Belan
  • 4,442
  • 3
  • 26
  • 48
0

Lodash if you don't mind

const orders=[{orderId:1,orderDate:"2021-04-28T08:20:58Z",status:"Confirmed",sellerName:"Chris Gilmour",revenue:2316.49},{orderId:2,orderDate:"2020-12-19T12:30:18Z",status:"Confirmed",sellerName:"Alanna Sumner",revenue:2928.88},{orderId:4,orderDate:"2020-12-24T08:00:09Z",status:"Confirmed",sellerName:"Beth North",revenue:1550.19},{orderId:5,orderDate:"2021-06-06T04:40:48Z",status:"Confirmed",sellerName:"Laura Ponce",revenue:35.5},{orderId:8,orderDate:"2021-08-27T05:13:40Z",status:"Canceled",sellerName:"Blade Newman",revenue:2957.29},{orderId:9,orderDate:"2020-12-26T08:07:57Z",status:"Confirmed",sellerName:"Alanna Sumner",revenue:2164.75},{orderId:10,orderDate:"2021-04-23T18:44:19Z",status:"Confirmed",sellerName:"Blade Newman",revenue:2287.55}];

const result = _.chain(orders)
  .groupBy('sellerName')
  .map((values, key) => ({ sellerName: key, totalRevenue: _.sumBy(values, 'revenue') }))
  .sortBy('sellerName')
  .value();

console.log(result);
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
A1exandr Belan
  • 4,442
  • 3
  • 26
  • 48