Calculate the total of all the arrays of objects nested within the main array of objects

I have an array of objects with nested arrays, and I need to calculate the sum of certain values based on the same picker_id. Specifically, I want to sum up the current_capacity, process_time_in_minutes, and picked_qty inside the products array. Here is the data:

var arr = [
  {
    current_capacity: 6000,
    picker_id: "icQrHPuE2fMZslceSG6liwuRar92",
    process_time_in_minutes: 10,
    products: [
      {
        product_id: 1,
        picked_qty: 2
      },
      {
        product_id: 2,
        picked_qty: 3
      }
    ]
  },

  {
    current_capacity: 2500,
    picker_id: "icQrHPuE2fMZslceSG6liwuRar92",
    process_time_in_minutes: 20,
    products: [
      {
        product_id: 1,
        picked_qty: 10
      }
    ]
  },

  {
    current_capacity: 36000,
    picker_id: "WIRzfIZALeftRk3DRGvh4nBdxQV2",
    process_time_in_minutes: 15,
    products: [
      {
        product_id: 1,
        picked_qty: 2
      },
      {
        product_id: 2,
        picked_qty: 3
      }
    ]
  }
];

Below is the code I'm using:

  var res = arr.reduce((acc, obj) => {
  var existObj = acc.find((item) => item.picker_id === obj.picker_id);
  if (existObj) {
    let total_picked = obj.products.reduce((acc2, curr) => acc2 + curr);

    // console.log("total_picked", total_picked);
    existObj.current_capacity =
      existObj.current_capacity + obj.current_capacity;
    existObj.process_time_in_minutes =
      existObj.process_time_in_minutes + obj.process_time_in_minutes;

    existObj.total = existObj.total ? existObj.total : 0 + total_picked;
    return acc;
  }
  acc.push(obj);
  return acc;
}, []);

const formatted = res.map((el) => {
  return {
    picker_id: el.picker_id,
    total_volume: el.current_capacity,
    total_time: el.process_time_in_minutes,
    total_products: el.total
  };
});

The resulting output is shown below:

[
 {
   picker_id: "icQrHPuE2fMZslceSG6liwuRar92"
   total_volume: 8500
   total_time: 30
   total_products: "0[object Object]"
 },
 {
   picker_id: "WIRzfIZALeftRk3DRGvh4nBdxQV2"
   total_volume: 36000
   total_time: 15
   total_products: undefined
  }
]

The expected output should be as follows:

[
 {
   picker_id: "icQrHPuE2fMZslceSG6liwuRar92"
   total_volume: 8500
   total_time: 30
   total_products: 15
 },
 {
   picker_id: "WIRzfIZALeftRk3DRGvh4nBdxQV2"
   total_volume: 36000
   total_time: 15
   total_products: 5
  }
]

Answer №1

By utilizing parameter destructuring, it is possible to enhance the code for better readability and efficiency. Here is an improved version based on the suggestions provided:

const extractData = (data) => Object .values (data .reduce (
  (acc, {capacity, id, time, products}) => {
    const currentPicker = acc [id] || (acc [id] = {
      id, totalVolume: 0, totalTime: 0, totalProducts: 0
    })
    currentPicker .totalVolume += capacity
    currentPicker .totalTime += time
    currentPicker .totalProducts += products .reduce ((acc, product) => acc + product .quantityPicked, 0)
    return acc
  },
  {}
))

const dataList = [{capacity: 6000, id: "icQrHPuE2fMZslceSG6liwuRar92", time: 10, products: [{productId: 1, quantityPicked: 2}, {productId: 2, quantityPicked: 3}]}, {capacity: 2500, id: "icQrHPuE2fMZslceSG6liwuRar92", time: 20, products: [{productId: 1, quantityPicked: 10}]}, {capacity: 36000, id: "WIRzfIZALeftRk3DRGvh4nBdxQV2", time: 15, products: [{productId: 1, quantityPicked: 2}, {productId: 2, quantityPicked: 3}]}]

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

Answer №2

This method can also produce the desired result:


    function calculateTotal(arr){
      let sum = 0;
      arr.forEach(item => {
        sum += item.quantity
      })
      return sum;
    }
    
    const finalResult = data.reduce((accumulator,element) => {
       if(!accumulator.hasOwnProperty(element.id)){
          accumulator[element.id] = {
            id: element.id,
            total_amount: element.amount,
            total_time: element.time_in_minutes
          }    
             
          accumulator[element.id].total_items = calculateTotal(element.items);
      }else{
         accumulator[element.id].total_amount = accumulator[element.id].total_amount + element.amount;
         accumulator[element.id].total_time = accumulator[element.id].total_time + element.time_in_minutes;
         accumulator[element.id].total_items = accumulator[element.id].total_items + calculateTotal(element.items);
      }
          
         return accumulator;
       },{});
        
console.log(Object.values(finalResult),'final result');

Answer №3

There was an issue in your implementation where if the existObj is not present in your acc, you were directly pushing the obj. Instead, you should process the total first from the inner array of products.

I have enhanced your code to make it more organized and maintainable.

Here is the approach:

  1. Create a dictionary for each unique picker_id that contains the computed data
  2. Convert the dictionary into a list
var result = arr.reduce((acc, obj) => {
  if (!acc[obj.picker_id]) {
    acc[obj.picker_id] = {
      total_volume: 0,
      total_time: 0,
      total_products: 0
    };
  }

  const selectedPicker = acc[obj.picker_id];
  const total_picked = obj.products.reduce((acc2, item) => acc2 + item.picked_qty, 0);

  selectedPicker.total_volume = selectedPicker.total_volume + obj.current_capacity;
  selectedPicker.total_time =
    selectedPicker.total_time + obj.process_time_in_minutes;
  selectedPicker.total_products = selectedPicker.total_products + total_picked;
  
  return acc;
}, {});


const formatted = Object.keys(result).reduce((acc, picker_id) => {
    acc.push({
    picker_id,
    ...result[picker_id]
  })
    return acc;
}, [])

console.log("formatted", formatted);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Activate jQuery datetimepicker on dynamic elements

Recently, I've been experimenting with a datetimepicker from here In my form, users have the ability to add more fields dynamically. Unfortunately, I haven't found a solution to make the datetimepicker work on these dynamically-added fields. If ...

Is it possible to load a JavaScript file from a different domain using a bookmarklet?

I'm a newcomer to bookmarklets and I am experimenting with loading a JavaScript file from my own server/domain using the following bookmarklet/javascript code: javascript:(function(){s=document.createElement('script'); s.type=' ...

Checking phone number on a React.js form

I am currently working on a front-end application and need to implement form validation. I am relatively new to ReactJS and learning as I go along in the development process. One of the input fields requires a phone number, which should only accept number ...

JavaScript can extract a portion of an array

Is it possible to generate a new array consisting of all elements ranging from the nth to the (n+k)th positions within an existing array? ...

Tips for displaying indentations on Tube Geometry using THREE.js

Currently, I have a project where I am tasked with displaying dents on a pipeline in a 3D format. To create the pipeline, I utilized THREE.js's tube geometry which is illustrated below: <!DOCTYPE html> <html lang="en"> <head> ...

Send data from an AJAX request to a Laravel controller

Here is the code for my ajax request where I am trying to pass values to a controller in Laravel. var deviceid="<?php echo $id; ?>"; var day="<?php echo $day; ?>"; $.ajax({ 'async': false, 'global': false, url ...

After a brief period of running, my AJAX request begins to malfunction

I'm attempting to automatically update two sections of my webpage every 4 seconds. Currently, my AJAX setup looks like this: setInterval(function () { autoUpdate() }, 4000); function autoUpdate() { $.get('/hello&a ...

Leveraging JQuery to extract the numerical value located between the slashes within a hyperlink

I need to extract numeric values from a link like this. For example: /produkt/114664/bergans-of-norway-airojohka-jakke-herre In this case, I want to fetch 114664. To achieve this, I have written the following jQuery code: jQuery(document).ready(functi ...

What is the best way to populate empty dates within an array of objects using TypeScript or JavaScript?

I am trying to populate this object with dates from today until the next 7 days. Below is my initial object: let obj = { "sessions": [{ "date": "15-05-2021" }, { "date": "16-05-2021" }, { "date": "18-05-2021" }] } The desired ...

Issues have been encountered with activating checkboxes on Internet Explorer while utilizing ASP.NET CheckBox controls

I'm facing an issue with an HTML form that includes two disabled checkboxes and an image with an onclick event intended to display a popup and enable the checkboxes: <input id="chk1" type="checkbox" disabled="disabled" /> <input id="chk2" ty ...

Using axios to modify and enhance the HTML content of a webpage

Utilizing axios and an API, I am able to retrieve a page's HTML, make edits to it, and then send it back via a POST request to the API. While successful in retrieving and editing the HTML content, I'm encountering difficulty in updating or changi ...

Measuring the number of distinct words within a given set of strings

Describing my attempt to create a function that processes string arrays by adding unique words to a word array, and incrementing the count of existing words in the count array: var words = []; var counts = []; calculate([a, b]); calculate([a, c]); funct ...

Developing a website with multiple pages using Vue.js CLI allows for

I am struggling to understand how to implement multiple pages in a Vue CLI project. Currently, I have my home page set up with a few components, but I am unsure of how to create additional pages. Should I be creating multiple HTML files where the index.htm ...

What could be causing the error in sending JSON data from JavaScript to Flask?

Check out this cool javascript code snippet I wrote: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script type=text/javascript> $(function() { $.ajax({ type: 'PO ...

Visualization with D3 - Putting an image at the heart of a circular chart made with SVG

Is it possible to add an image to the center of a donut SVG in D3 charts using JavaScript? I've been attempting to achieve this but haven't had any success so far. Currently, I have inserted the image in HTML, but it does not align with the cent ...

Utilizing a font URL imported through a script

I am currently working on incorporating the pdfmake package into my application. In order to load fonts, a list of URLs is required during initialization. However, the fonts I am using are managed by npm and Vite, so they do not have fixed URLs. Here' ...

Automating Image Downloads with Puppeteer by Adding Authentication Query String to Image URL

Attempting to save images stored in a web-space account can be challenging. Accessing the private space with credentials and retrieving the image link using Puppeteer works smoothly. However, when the src attribute of the image includes additional authenti ...

Updating class on elements in arrays

There are multiple elements, each with a unique ID "xxx_view_ch_&&&" within an outer div with the ID "xxx_view_&&&". The goal is to change the class of the element with the ID "xxx_view_ch_&&&" when the user clicks on the entire element ("xxx_view_&&&"). ...

What is the most efficient way to perform an array join in Node.js, akin to the speed of MongoDB's $

Looking to implement a $lookup function in Node.js similar to the $lookup aggregation in MongoDB. I have a solution in mind, but I'm unsure about its performance when dealing with larger arrays or bigger objects. let users = [ {userId: 1, name: ...

Guide to refreshing extensive dataset using MySQL migration scripts

We are in the process of developing a Nodejs application for a client who has requested that we use migration scripts to streamline updating the production database. As someone new to MySQL, I am struggling with how to update table contents using only MySQ ...