Adding up values in JavaScript object

After fetching JSON data from an API, I am using the map function to create my own object structure.

The data consists of multiple objects. An example of the data structure is as follows:

{
  "data": {
    "job": [
      {
        "jobNumber": "1",
        "jobTasks": {
          "jobTask": [
            {
              "total": { "amountString": "10.00" }
            },
            {
              "total": { "amountString": "10.00" }
            }
          ]
        }
      },
      {
        "jobNumber": "2",
        "jobTasks": {
          "jobTask": [
            {
              "total": { "amountString": "20.00" }
            },
            {
              "total": { "amountString": "20.00" }
            }
          ]
        }
      },
      {
        "jobNumber": "3",
        "jobTasks": {
          "jobTask": [
            {
              "total": { "amountString": "30.00" }
            },
            {
              "total": { "amountString": "30.00" }
            }
          ]
        }
      }
    ]
  }
}

Based on the provided example, I aim to achieve the following results:

jobNumber: 1 - Total 20. jobNumber: 2 - Total 40. jobNumber: 3 - Total 60.

Below is the code snippet that I am using:

var array = response.data.map(function(item, array) {

   var sumTaskTotal = item.jobTasks.reduce(function(sumTaskTotal, item, index) {
       if (item !== null && item.total !== null) {
          sumTaskTotal += item.total.amountString;
          return sumTaskTotal;
       }
    }, 0);

    array = response.data.map(item => ({
      jobNumber: item.jobNumber,
      sumTaskTotal: sumTaskTotal,
    }));
}

However, the sum calculation keeps accumulating, resulting in:

jobNumber: 1 - Total 120. jobNumber: 120 - Total 120. jobNumber: 3 - Total 120.

I have experimented with for loops but haven't yet found a solution.

Answer №1

It's a bit unclear how you ended up with the result of

jobNumber: 1: Total 120. jobNumber: 120: Total 120. jobNumber: 3: Total 120.
. When I tested your code, the array logged showed that it contained 3 undefined items; this is because each iteration within the map function doesn't return anything.

Furthermore, both data and jobTasks are objects. You need to use map or reduce methods on the properties like job and jobTask.

In terms of adding totals, remember that amountString is a string, so you should convert it to a number first. Otherwise, concatenating a string to a number will not result in addition, as shown by 010.00 in your initial iteration.

The outer map function where array = response.data.map... would just reiterate through the jobs again unnecessarily. Instead, consider simplifying it to:

return {
  jobNumber: item.jobNumber,
  sumTaskTotal,
};

This modification would yield an array with 3 objects:

[{
  jobNumber: '1',
  sumTaskTotal: 20,
}, {
  jobNumber: '2',
  sumTaskTotal: 40,
}, {
  jobNumber: '3',
  sumTaskTotal: 60,
}]

If you prefer, you can implement a nested reduce approach:

const formatted = response.data.job.reduce((prevString, currentJob) => {
  const total = currentJob.jobTasks.jobTask.reduce((prevTotal, currentJobTask) => {
    return prevTotal + Number(currentJobTask.total.amountString);
  }, 0);

  return `${prevString}jobNumber: ${currentJob.jobNumber}: Total ${total}. `;
}, '');

const response = {
  "data": {
    "job": [{
      "jobNumber": "1",
      "jobTasks": {
        "jobTask": [{
          "total": {
            "amountString": "10.00"
          }
        }, {
          "total": {
            "amountString": "10.00"
          }
        }]
      }
    }, {
      "jobNumber": "2",
      "jobTasks": {
        "jobTask": [{
          "total": {
            "amountString": "20.00"
          }
        }, {
          "total": {
            "amountString": "20.00"
          }
        }]
      }
    }, {
      "jobNumber": "3",
      "jobTasks": {
        "jobTask": [{
          "total": {
            "amountString": "30.00"
          }
        }, {
          "total": {
            "amountString": "30.00"
          }
        }]
      }
    }]
  }
};

const formatted = response.data.job.reduce((prevString, currentJob) => {
const total = currentJob.jobTasks.jobTask.reduce((prevTotal, currentJobTask) => {
  return prevTotal + Number(currentJobTask.total.amountString);
  }, 0);
  
  return `${prevString}jobNumber: ${currentJob.jobNumber}: Total ${total}. `;
}, '');

console.log(formatted.trim());

Answer №2

Simply utilize the forEach method to retrieve your desired string.

const data = {
  "data": {
    "job": [
      --
    ]
  }
}

let string = "";

data.data.job.forEach((item) => {
  const sum = item.jobTasks.jobTask.reduce((total, i) => parseFloat(i.total.amountString) + total, 0);
  string += `jobNumber: ${item.jobNumber}: Total ${sum}. `;  
});
console.log(string);

Check out this example on jsbin for reference

Remember to watch out for an unnecessary space after your string and use the trim function if needed.

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

The Angular2 Http request isn't being triggered

Context : After following multiple tutorials, I have been experimenting with authentication in Angular2 using JWT. I have created a component and a service named: app.component.ts user.service.ts The app component (along with its template) contains a s ...

Utilizing ng-style with a ForEach loop on an Object

How can I dynamically add a new style property to objects in an array in Angular, and then use that property inside ng-style? CommentService.GetComments(12535372).then(function () { $scope.comments = CommentService.data(); angular.forEac ...

Running a JavaScript file from Docker to fill a MongoDB database is not working when using the WSL shell on Windows 10

I'm facing some issues while trying to populate my MongoDB using a script. Every time I run the script, I encounter errors even though the Docker container is up and running. For reference, I'm on Windows 10 using WSL shell. https://i.stack.img ...

A situation arises where the third-party library (react-dev-utils/webpackHotDevClient) is unable to retrieve the necessary data when requiring the 'chalk' object,

Currently, I am operating a react application through the Webpack development server. In my configuration settings, 'react-dev-utils/webpackHotDevClient' is included in the entry array. Unfortunately, this setup results in the following error me ...

Populate items on the webpage with data from a JSON document

Looking for a more efficient way to handle text in my multilanguage web application. I currently store all text in a JSON file and load it for each element on every page using JQuery, like this: $("h1.text1").append(data[language]['startpage'][0 ...

Html Canvas Overlay that allows content underneath to remain interactive

Trying to layer the canvas outlined in red over the div with a black border that is currently underneath. The canvas should match the size of the div, and I need to be able to interact with buttons and text beneath it. I've been at this for 48 hours a ...

The testcafe selector fails to locate any 'div' elements

I've encountered a strange issue with testcafe. When testing one of my websites, I'm unable to select div elements, but I can select other types of elements without any problem. For example: await t.click(Selector("span").withAttribute( ...

Obtain a JSON object in C# through a web request

I'm trying to fetch JSON data from an external domain using a webrequest. Here's the code snippet I used: var search = umbraco.library.Request("search"); string Url = "http://ff.ss.dk/Suggest.ff?username=us&password=pass&channel=dk&f ...

Is it possible to convert a string using object-to-object syntax?

After running a particular function, I received the following results: [ "users[0].name is invalid", "date is invalid", "address.ZIP is invalid" ] I am looking for a way to convert this output from object syntax i ...

What is the process for updating the label on the leaflet control layers toggle?

I have incorporated mapbox and leaflet into my website, and I'm looking to modify the label "Satellite" in leaflet-control-layers-toggle to "SAT". Is there a way to achieve this change using leaflet? https://i.sstatic.net/DAR9m.png ...

div consistently positioned above fixed element

My goal is straightforward - I have a fixed div at the bottom of my page that always needs to be visible. Inside this div, there are two sub-divs; one small div should always be on top, and the other should be scrollable. The issue lies with the small div ...

Generate tables and rows dynamically

I am looking for guidance on dynamically creating a table and adding rows to it. I have successfully created a table with one row containing form fields, but I am unsure how to add additional rows. Any examples or suggestions on how this can be implemented ...

Encountering complications while attempting to integrate Ng-SweetAlert-2 into AngularJS

Concerning this particular project After following the installation process outlined in the description, I encountered an error: Error: [$injector:unpr] Unknown provider: 19degrees.ngSweetAlert2Provider <- 19degrees.ngSweetAlert2 <- prkctrl` I hav ...

leveraging UI-Router for navigating based on app state and data

Is there a way to dynamically adjust Angular's ui-routing based on certain data conditions? For instance, let's say we need to create a subscription process where the user is informed of whether their subscription was successful or not. As the f ...

Retrieve data from a specific field in a JSON response

I am attempting to retrieve a specific field from an API request, which will be utilized for another task. My goal is to automate this request in order to keep track of the timestamp of the remote machine. Here is the script I have created to obtain the j ...

What steps are needed to generate an Observable that contains boolean values?

I am looking to create an Observable that can emit a boolean value and be modified by a function. My attempt was: showModal$ = new Observable<boolean>(); Unfortunately, this approach did not work as expected. What I really need is for showModal$ ...

Tips for displaying the node's label in Arbor js when hovering over the node

I'm currently utilizing Arbor Javascript to exhibit a graph composed of nodes and edges. My objective is to have the node's label displayed when the mouse hovers over it within the graph. Below is the code snippet I am working with: <canvas i ...

Yii2 paired with Ajax: The output does not consist of the SQL query outcomes

I am facing an issue with executing an AJAX query using jQuery as the response is not as expected. On the client side: $.ajax({ url: "/family?idperson=1234", dataType: 'json', success: function(res) { console.log(JSON.string ...

Discover the most recent date of a document by analyzing two distinct fields: the month and the year

In my mongoDB database, the documents have the following structure: {username:String, paymentYear:Int, paymentMonth:Int} I am trying to retrieve the latest document for a specific username, which would be the one with the date closest to the current Date ...

Inner output not displaying on the screen

Based on the outcome of the graphql query, certain items are generated within the function contact export const Whitelist: React.FunctionComponent = (props) => { const [userData, setUserData] = useState<UsersQueryHookResult>(''); c ...