Home > OS >  Make an array from array of array of objects with same property
Make an array from array of array of objects with same property

Time:12-08

I have an javascript array and it contains another array of objects. Now I want to do sum of the field of objects having same symbol key. How to do that ?

The array I have

let orders = [
    {
        "_id": "6c18cea3-7d37-4f85-b369-abf03e7ff873",
        "subOrders": [
            {
                "symbol": "SUZ",
                "fulfilledQty": "49.333991119"
            },
            {
                "symbol": "FSLR",
                "fulfilledQty": "2.895864705"
            }
        ]
    },
    {
        "_id": "acf75fcb-496a-4825-b7bc-cef60556fe49",
        "subOrders": [
            {
                "symbol": "FSLR",
                "fulfilledQty": "1"
            },
            {
                "symbol": "SUZ",
                "fulfilledQty": "1"
            }
        ]
    },
    {
        "_id": "e32041a1-17f0-44c4-9fc4-4619e0507392",
        "subOrders": [
            {
                "symbol": "SUZ",
                "fulfilledQty": "8.751458576"
            },
            {
                "symbol": "FSLR",
                "fulfilledQty": "0.587774294"
            }
        ]
    }
]

The array I want from above array

[
    {
        "symbol": "FSLR",
        "fulfilledQty": "4.483638999"
    },
    {
        "symbol": "SUZ",
        "fulfilledQty": "59.085449695"
    }
]

So I want to the sum of fulfilledQty of same symbol

I tried this


let totalOrder = {};
   for(let order of orders){
      for(subOrder of order.subOrders){
         totalOrder[subOrder.symbol] = totalOrder[subOrder.symbol] ? 
            parseFloat(totalOrder[subOrder.symbol])   
            parseFloat(subOrder.fulfilledQty) : 
            parseFloat(subOrder.fulfilledQty);
         }
}

That gives me this object

{SUZ: "59.085449695", FSLR: "4.483638999"} 

then I will convert it to array. Because Inside inner for loop I will have to put another loop to compare the symbols So this will not iterate each time to compare symbols That can be achieved using the loops but do so I will have to iterate the arrays too many times Is there any simpler way to do so ?

CodePudding user response:

You can use a .reduce() to sum up the qty by symbol, then map that into the desired array:

const input = [
  {
    "_id": "6c18cea3-7d37-4f85-b369-abf03e7ff873",
    "subOrders": [
      { "symbol": "SUZ",  "fulfilledQty": "49.333991119" },
      { "symbol": "FSLR", "fulfilledQty": "2.895864705" }
    ]
  },
  {
    "_id": "acf75fcb-496a-4825-b7bc-cef60556fe49",
    "subOrders": [
      { "symbol": "FSLR", "fulfilledQty": "1" },
      { "symbol": "SUZ",  "fulfilledQty": "1" }
    ]
  },
  {
    "_id": "e32041a1-17f0-44c4-9fc4-4619e0507392",
    "subOrders": [
      { "symbol": "SUZ",  "fulfilledQty": "8.751458576" },
      { "symbol": "FSLR", "fulfilledQty": "0.587774294" }
    ]
  }
];
let sums = input.reduce((acc, obj) => {
  obj.subOrders.forEach(item => {
    let symbol = item.symbol;
    let qty = Number(item.fulfilledQty);
    if(!acc[symbol]) {
      acc[symbol] = qty;
    } else {
      acc[symbol]  = qty;
    }
  });
  return acc;
}, {});
let result = Object.keys(sums).sort().map(symbol => {
  return {
    symbol: symbol,
    fulfilledQty: sums[symbol].toString()
  };
});
console.log(result);

CodePudding user response:

As you have mentioned you are getting the array from mongodb then you can make a aggregation pipeline.

              let aggregation = [
                    {
                      '$match': {
                         //Your query here
                       }
                    }, {
                      '$unwind': {
                        'path': '$subOrders'
                      }
                    }, {
                      '$group': {
                        '_id': '$symbol', 
                        'symbol': {'$first': "$symbol"},
                        'total': {
                          '$sum': {
                            '$toDouble': '$fulfilledQty'
                          }
                        }
                      }
                    }
                  ]

CodePudding user response:

We can use Array.flatMap() and Array.reduce() to do it

let result = orders.flatMap(e => e.subOrders).reduce((a,{symbol,fulfilledQty}) => {
  a[symbol] = a[symbol]??0
  a[symbol]  =  fulfilledQty
  return a
},{})
console.log(result)

let orders = [
    {
        "_id": "6c18cea3-7d37-4f85-b369-abf03e7ff873",
        "subOrders": [
            {
                "symbol": "SUZ",
                "fulfilledQty": "49.333991119"
            },
            {
                "symbol": "FSLR",
                "fulfilledQty": "2.895864705"
            }
        ]
    },
    {
        "_id": "acf75fcb-496a-4825-b7bc-cef60556fe49",
        "subOrders": [
            {
                "symbol": "FSLR",
                "fulfilledQty": "1"
            },
            {
                "symbol": "SUZ",
                "fulfilledQty": "1"
            }
        ]
    },
    {
        "_id": "e32041a1-17f0-44c4-9fc4-4619e0507392",
        "subOrders": [
            {
                "symbol": "SUZ",
                "fulfilledQty": "8.751458576"
            },
            {
                "symbol": "FSLR",
                "fulfilledQty": "0.587774294"
            }
        ]
    }
]

let result = orders.flatMap(e => e.subOrders).reduce((a,{symbol,fulfilledQty}) => {
  a[symbol] = a[symbol]??0
  a[symbol]  =  fulfilledQty
  return a
},{})
console.log(result)

  • Related