JavaScript code that compares dates in an array, then calculates the total price for each month and year

I have a JSON file containing various transactions with both a date and a price attribute. My goal is to compare the dates, identify transactions that occur in the same month and year, and calculate the total price of those transactions.

JSON:

transactions: [
{
  date: "2017-11-17",
  price: "28",
},
{
  ...
}

JavaScript:

request.onload = function() {
  for(const transaction of request.response.transactions) {
    let year = new Date(transaction.date).getFullYear();
    let month = new Date(transaction.date).getMonth();

    console.log(year + ' ' + month);  // output: 2017-11 ...
  }
};

Although I attempted to iterate through the JSON object, I am currently struggling to devise a method for comparing the dates effectively.

Answer №1

Note: Updated example using Object.assign instead of Object spread.

To calculate the total sum of prices, you will need to utilize the reduce method. Refer to the comments for more information.

const transactions = [{
    date: "2017-11-17",
    price: "28",
  },
  {
    date: "2017-12-17",
    price: "23",
  },
  {
    date: "2017-11-17",
    price: "12",
  },
  {
    date: "2017-10-17",
    price: "55",
  },
  {
    date: "2017-11-17",
    price: "09",
  },
];

const sumTransactions = (transactions) => {

  const summed = transactions.reduce((acc, current) => {
    // Obtain the current date object
    const date = new Date(current.date);
    // Create a key/identifier
    const key = `${date.getFullYear()}-${date.getMonth() + 1}`;
    // Retrieve the previous price from the accumulator
    const previousPrice = acc[key]; 
    // Set up the current price value and ensure it is treated as a number.
    let currentPrice = Number(current.price);
    // If there was a previous value (not undefined)
    if (previousPrice) {
      // Add it to our current value
      currentPrice += Number(previousPrice);
    }
    // Return the updated accumulator value
    return Object.assign(acc, {
      [key]: currentPrice, 
    })
  }, {})

  // Once all values are calculated, extract dates and sort them in ascending order.
  // Create an array with each value from the summed object in sortedArray
  const sortedArray = Object.keys(summed).sort().map((val) => {
    return summed[val];
  });

  console.log("sortedArray", sortedArray);
};

sumTransactions(transactions);

Answer №2

After some experimentation, I managed to find a solution that works:

var transactions = [
    {
        date: "2017-11-17",
        price: "28",
    },
    {
        date: "2017-12-17",
        price: "22",
    },
    {
        date: "2017-12-17",
        price: "20",
    }
]

var sumedUpDates = [];
var prices = [];

function isDateSumedUp(date) {
    return sumedUpDates.indexOf(date.substring(0, 7)) !== -1;
}

function sumUpDate(date) {
    var sum = 0;

    transactions.forEach(t => {
        if(t.date.substring(0, 7) === date.substring(0, 7)) {
            sum += parseInt(t.price);
        }
    });

    sumedUpDates.push(date.substring(0, 7));
    prices.push(sum);
}

transactions.forEach(t => {
    if(!isDateSumedUp(t.date)) {
        sumUpDate(t.date);
    }
});

var obj = {};

sumedUpDates.forEach((d, i) => obj[d] = prices[i]);

console.log(obj);

Answer №3

This method utilizes the map function to convert dates in each object entry into a year/month format, and then uses the reduce function to sum them based on those separated dates.

const transactions = [
  {date:"2017-11-17", price: "28",}, 
  {date:"2017-12-17", price: "28",}, 
  {date:"2017-11-17", price: "20",},
  {date:"2017-12-17", price: "2",}, 
  {date:"2017-11-17", price: "58",}, 
  {date:"2017-11-17", price: "8",}, 
  {date:"2017-10-17", price: "30",}, 
  {date:"2018-11-17", price: "1",},
];

const mapper = single => {
  let d = single.date.split('-');
  let p = Number(single.price);
  return { year: d[0], month: d[1], price: p };
}

const reducer = (group, current) => {
  let i = group.findIndex(single => (single.year == current.year && single.month == current.month));
  if (i == -1) {
    return [ ...group, current ];
  }

  group[i].price += current.price;
  return group;
};

const totalPricesByDate = transactions.map(mapper).reduce(reducer, []);
console.log(totalPricesByDate);
  

Answer №4

let data = [];
for (let i = 0; i < transactions.length; i++) {
    let date = new Date(transactions[i].date);
    let ym = date.getFullYear() + "-" + date.getMonth();
    if (data[ym] == null) {
        data[ym] = 0;
    }
    data[ym] += parseInt(transactions[i].price);
}

Using the provided information

let transactions = [{
                date: "2017-11-17",
                price: "28",
            },
            {
                date: "2017-12-17",
                price: "5",
            },
            {
                date: "2016-02-17",
                price: "28",
            },
            {
                date: "2015-11-17",
                price: "25",
            },
            {
                date: "2016-02-17",
                price: "12",
            },
            {
                date: "2017-11-17",
                price: "50",
            }
        ];

This code will sum up all duplicates of year-months like this :

[
    2017-10: 78, 
    2017-11: 5, 
    2016-1: 40, 
    2015-10: 25
]

Answer №5

One alternative approach is to use the reduce method:

const transactions = [
  {date: "2020-05-15", price: "35"},
  {date: "2020-06-20', price: "50"},
  {date: "2020-06-30", price: "45"}
];

const result = transactions.reduce((acc, obj) => {
  const key = obj.date.substr(0,7);
  acc[key] = (acc[key] || 0) + +obj.price;
  return acc;
}, Object.create(null));

console.log(result);

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

Creating a popup with multiple tabs using CSS

Struggling to navigate through the intricacies of these code snippets <!DOCTYPE html> <html lang ="en"> <head> <style type="text/css"> a{ text-decoration:none; color:#333; } #pop{ width:557px; height:400px; background:#333; ...

The error message "UnhandledPromiseRejectionWarning: Error: ENOTEMPTY: directory not empty" typically occurs

Struggling to successfully run the build using npm run build. Encountering the following error: UnhandledPromiseRejectionWarning: Error: ENOTEMPTY: directory not empty, rmdir '/var/www/html/abhinav/png-react/png-compressor/build/static' ...

Scope challenges with making multiple rest calls in Angular.js

As a beginner in Angular.js, I am facing an issue with $scope not receiving additional value from one of two $resource rest calls. Below is the code snippet: controller: function ($scope, $modalInstance, $route) { $scope.server = {} ...

In Java, combine values from two distinct ArrayLists and store them in a single array object

Currently, I am attempting to generate an update SQL query from a CSV file. To achieve this, I need to compare values from two separate array lists - one sourced from the CSV file, and the other from the database. The goal is to update my Books Database w ...

Unable to retrieve $scope.property using direct access, however it is visible when printed to the console using console.log($

I have successfully populated $scope with data using a get call: httpGetAsync("myUrlWasHere", getBlogPosts, $scope); The console outputs the data when I print console.log($scope): https://i.sstatic.net/SkDl9.png However, when I try to access it using c ...

Requesting data from a server using jQuery's AJAX functionality

Currently, I am utilizing the following piece of code for an ajax call: $('#filter').submit(function(){ var filter = $('#filter'); $.ajax({ url:filter.attr('action'), data:filter.serialize(), // form ...

Why isn't the array loading upon the initial click in AngularJS?

// CONFIGURING SERVICES app.service("PictureService", function($http) { var Service = {}; Service.pictureLinkList = []; // RETRIEVING PICTURE LINKS FOR THE PAGE $http.get("data/img_location.json") .success(function(data) { Service.pictureLinkLi ...

The JSON file overwrites entire objects instead of targeting individual ones

Is there a way to update just one specific object in a JSON file without affecting the rest? I've implemented a put request on the front-end using axios to send data to the back-end for processing. However, the current functionality replaces all obje ...

Is it possible to enable tab navigation for a button located within a div when the div is in focus?

I have a component set up like this: (Check out the Code Sandbox example here: https://codesandbox.io/s/boring-platform-1ry6b2?file=/src/App.js) https://i.sstatic.net/ZuxdL.png The section highlighted in green is a div. Here is the code snippet: import { ...

Issue: When calling setState(...), you must provide either an object containing the state variables to update or a function that will return an object with the updated

Encountering an error in the else section with this.state.incorrect + 1 and this.state.correct + 1 I've come across a similar issue that wasn't resolved by visiting this link: React Native: setState(...): takes an object of state variables to up ...

The GET method for accessing JSON data is now eliminating any leading zeros in the

When attempting to utilize jQuery to send the string "0002" to a WebMethod, I am encountering an issue where the leading zeros are being removed. $.ajax({ type: "GET", url: "CallNote.aspx/GetStoreRegion?storeCode=0002", contentType: "application/jso ...

How can I implement an AJAX request with MongoDB in Node/Express?

Let's begin with a simple webpage: an HTML Form, a button, and a div-box. When the button is clicked, the Form data will be sent via AJAX. The data will then be stored in MongoDB and retrieved into the div-box seamlessly without any page refresh. A ...

"Before the click even happens, the jquery click event is already

As I was developing a small todo app, I ran into an issue where the alert message seemed to pop up before the click event was triggered. It almost seems like the event is not registered properly. Can someone explain why this is happening? (function() { ...

Utilizing various Firestore requests at varying intervals using the useEffect hook in React

useEffect(async() => { await getWord(); const interval = setInterval(() =>{ time2 = time2 - 1; if (time2 == 0) { clearInterval(interval); let dataURL = canvasRef.current.toDataURL(); const db = firebase.firestore(); ...

I am interested in obtaining every separate return value from the reduce() function instead of just the final total

initialValue currentValue position elements final value first calculation 0 1 1 [0, 1, 2, 3, 4] 1 second run 1 2 2 [0, 1, 2, 3, 4] 3 third round 3 3 ...

Stop the link action following a delay after the mouse is clicked

I'm currently troubleshooting a function that should prevent users from being redirected when clicking and holding onto a link for more than one second. However, the function I implemented is not functioning as expected. I have spent some time reviewi ...

What is the best way to stack animations in CSS and HTML?

I need help figuring out how to layer two different animations on my website. Specifically, I want to create an effect where twinkling stars are in the background with a moving moon animation layered on top of them. However, when I try to implement this, t ...

Transferring files from the android_asset directory to the SD Card

I am trying to play video files that are packaged within a Cordova application. My goal is to transfer these files from the android_asset folder to the SD card using the File API in JavaScript. However, I am encountering difficulties in accessing this fol ...

How can you define a variable within the .config service in Angular JS?

Here is the code snippet I have been working on: spa.factory("linkFactory", function() { var linkFactoryObject = {}; linkFactoryObject.currentLink = "home"; return linkFactoryObject; }); This piece of code essentially serves as a global varia ...

How to store data in a JSON file using Python functions and return statements

I'm facing an issue trying to insert the returned dictionary from the function getvalues into "data.update". Although I can add it as a separate JSON object, adding it inside the fields key seems to be problematic. Could you please review the output a ...