Leveraging the .reduce method to perform specific calculations and generate an object containing the results of an array

After successfully achieving the desired results, here is the data manipulation I have done:

const days = [
{
    date: '2016-12-13T00:00:00.000Z',
    stats: [
      { name: 'Soft Drinks', sold: 34, },
      { name: 'Snacks', sold: 3, },
      { name: 'Coffee and warm drinks', sold: 26, },
    ],
  },
  {
    date: '2016-12-14T00:00:00.000Z',
    stats: [
      { name: 'Soft Drinks', sold: 34, },
      
      { name: 'Snacks', sold: 3, },
      { name: 'Coffee and warm drinks', sold: 26, },
    ],
  },
];

const newStats = days.reduce(function (pastDay, currentDay) {
  const nextStats = currentDay.stats.map(function(stat) {
  const oldSold = pastDay.stats.find(function (old) {
    return old.name === stat.name;
    });
    
  const newSold = stat.sold + oldSold.sold;
  stat.sold = newSold;
    return stat;
  });

  return {
    stats: nextStats,
  };
});

console.log(newStats);

The output I obtained is:

{
  "stats": [
    {
      "name": "Soft Drinks",
      "sold": 68
    },
    {
      "name": "Snacks",
      "sold": 6
    },
    {
      "name": "Coffee and warm drinks",
      "sold": 52
    }
  ]
}

While the initial structure worked perfectly, I encountered an issue when applying the same logic to a different array of objects. The error message "undefined error on pastDay" is appearing. Can someone assist in identifying the problem or suggesting an alternative to the .reduce method?

Below is the array causing the problem:

const days = [  
   {  
      "_id":{  
         "_str":"f23f02994ab992437e423e24"
      },
      "date":"2016-12-13T00:00:00.000Z",
      "statistics":{  
         "breakdown":{  
            "byTurnover":[  
               {  
                  "name":"Soft Drinks",
                  "sold":34,
                  "percentage":31.14
               },
               
               <snippet shortened for brevity>
               
            ],
         }
      },
      "id":{  
         "_str":"f23f02994ab992437e423e24"
      }
   },
   <snippet shortened for brevity>
   {  
      "_id":{  
         "_str":"e1906ce07ab811c74528e3cc"
      },
      "date":"2016-12-15T00:00:00.000Z",
      "statistics":{  
         "breakdown":{  
            "byTurnover":[  
               <snippet shortened for brevity>
            ],
         }
      },
      "id":{  
         "_str":"e1906ce07ab811c74528e3cc"
      }
   },
];

const newStats = days.reduce(function (pastDay, currentDay) {
  const nextStats = currentDay.statistics.breakdown.byTurnover.map(function(stat) {
  const oldSold = pastDay.statistics.breakdown.byTurnover.find(function (old) {
    return old.name === stat.name;
    });
    
  const newSold = stat.sold + oldSold.sold;
  stat.sold = newSold;
    return stat;
  });

  return {
    stats: nextStats,
  };
});

console.log(newStats);

Upon running the code for the second array, the following error was encountered:

Uncaught TypeError: Cannot read property 'breakdown' of undefined

Here is the .reduce code for the second array:

const newStats = days.reduce(function (pastDay, currentDay) {
  const nextStats = currentDay.statistics.breakdown.byTurnover.map(function(stat) {
    const oldSold = pastDay.statistics.breakdown.byTurnover.find(function (old) {
        return old.name === stat.name;
    });

    const newSold = stat.sold + oldSold.sold;
    stat.sold = newSold;
    return stat;
  });

  return {
    stats: nextStats,
  };
});

console.log(newStats);

Answer №1

Your initial reducer is returning an object in a format that aligns with the input array structure, like this:

return {
    stats: nextStats,
};

Here is how your array is structured:

const days = [{ stats: [...] }]

Therefore, when the inner loop iterates over .stats as an array, it will operate correctly.

Your second reducer is looping over an object with the following structure:

const days = [{ statistics: { breakdown: { byTurnover: [...] } }]

However, it then returns an object that does not match that structure:

return {
    stats: nextStats,
};

As a result, the first iteration of the reducer will function properly, but the subsequent iteration will encounter an issue. The first argument, pastDay, will be the return value of the previous run, which may not have the keys you expect.

An easy fix is to ensure that the object key depth matches when returning:

const newStats = days.reduce(function (pastDay, currentDay) {
    const nextStats = currentDay.statistics.breakdown.byTurnover.map(function(stat) {
        const oldSold = pastDay.statistics.breakdown.byTurnover.find(function (old) {
            return old.name === stat.name;
        });

        const newSold = stat.sold + oldSold.sold;
        stat.sold = newSold;
        return stat;
    });

    return {
        statistics: { breakdown: { byTurnover: nextStats } },
    };
});

While this provides a solution, the logic used may be difficult to follow. Depending on your goals, which are not entirely clear from the code, this approach may not be the most efficient.

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

A guide on calling a function from a different component in vuejs2

I am facing a situation where I need to trigger an event whenever my sidebar opens. This event should be called every time the sidebar is opened. For example, when I click on an element, it triggers the opening of my sidebar which then calls a function th ...

Using external scripts that require access to the DOM and window object within a Javascript/Node.js Azure Function: Best practices

I am attempting to integrate external JavaScript into an Azure Function that uses the JavaScript/Node.js flavor. The external JavaScript library I need to use, Kendo, relies on a DOM and a window. To achieve this, I initially experimented with JSDOM, but I ...

"Utilize AJAX to submit the value of the text box input from a jQuery slider when the Submit Button

Whenever I adjust the sliders, the value is shown in an input textbox. However, when I move the slider and check the values echoed from the textboxes on another PHP page, they are always displaying as 0. Even after clicking the submit button, it still echo ...

While my other function remains incomplete, AngularJS $http continues to run without interruption

I'm facing an issue in my AngularJS function where the $http request is being fired before my first function is completed. Here's a sample of how my code looks: $scope.function = function(){ $scope.functionOne(); // This function initializ ...

Create a division that will remain visible on the screen and allow scrolling when a certain class is

Having some trouble with a fixed class div that is not continuing to scroll after the class is removed on scroll. I've attempted to fix this issue but the div keeps getting hidden instead of continuing to scroll. If anyone has any advice or can poin ...

Using an AngularJS directive to modify CSS styles

I'm attempting to modify DOM CSS styles using Angular. If the textbox value is set as the height, I have assigned ng-model to the textbox and then ng-style="{height:heightdef}" How can I achieve this using a directive? Fiddle :: http://jsfiddle.n ...

Encountering timeout issues while implementing routes in VueJS

Currently, I am utilizing VueJS to send data to the server and then navigate to another route. I attempted the following code: saveSupportArea: function () { this.toast("success"); var that = this; setTimeout(function(that){ that.$rou ...

Display JSON data from a URL in a listview on an Android application using a straightforward parsing method

I need help with parsing a JSON response from a URL within my Android application... I've attempted several methods found online, but I'm unable to successfully parse it. The JSON content appears as follows: [ { "city_id": "1", ...

React Grid by DevExtreme

Does anyone have a solution for adjusting the fontSize of the TableHeaderRow in a DevExtreme React Grid? Here is some code from a specific website () that I've been exploring: import * as React from 'react'; // Other imports... const Ad ...

What is the most efficient way to apply a single click handler instead of using multiple click handlers for the same

Check out the project I'm currently working on by following this link: The link provided above contains a list of clickable colors available on the right side. When a user clicks on a color, the images on the left side change accordingly. Below is t ...

Tips for inserting data into a specific position within an array

I am working with an array that currently contains only usernames, which I have added using array_push within a foreach loop: array(4) { [0]=> string(13) "Username1" [1]=> string(10) "Username2" [2]=> string(12) "Username3" [3]=> ...

What is the most effective way to show an error message within the login form itself?

I'm currently dealing with a dilemma involving my login.php and login_process.php files. The login form is in the former, while the validation process occurs in the latter. I'm struggling to figure out how to display error messages on the login f ...

Manipulate values within an array when a checkbox is selected or deselected

I am developing an Angular application where I have created a checkbox that captures the change event and adds the checked value to an array. The issue I am facing is that even if the checkbox is unchecked, the object is still being added to the array. D ...

Exclude objects with similar ids using a method other than JavaScript's filter()

I have a list of students who need to receive medication multiple times throughout the day. The challenge is to filter the array to track how many times each student receives the same medication. The list includes three different students and repeats the s ...

Include an additional parameter in a Google search query

For some time, I've been attempting to retrieve real-time stock quotes from Google. Initially, I tried using the finance API but unfortunately, that didn't work out as expected. However, I stumbled upon this query and it appears to be too good t ...

Combine the information from two dictionaries to create a single json object

I am attempting to convert two dictionaries into a JSON format consecutively using Python. I have created two dictionaries that appear as follows --- dictionary_quant = {'dmin': [0.003163, 14.325], 'magNst': [0.0, 414.0], 'horizon ...

What is the best way to empty a backbone collection in preparation for loading new data?

Hey everyone, I've been working on a Backbone application that involves adding and deleting or editing images. Currently, I'm using a router to navigate between different sections like the gallery and forms. However, whenever I make changes in th ...

Discovering the name, id, and class attributes of a RadioButtonList within a content placeholder using JavaScript

Working on a web forms project with a Master Page implementation, I have added the following code in my content place holder. <asp:RadioButtonList ID="ckbLstPartner" runat="server" name="ckbLstPartner" RepeatDirecti ...

Alter the color scheme of the website depending on the information provided by the user on the previous page

On the previous page, I have created a form with a checklist containing options for colors: red, green, and blue. If the user selects red, the background color on the next page should change to red. If green is selected, the background color will be green ...

Load External HTML content into webpage along with executing JavaScript code and triggering JS functions upon loading

I'm in search of a super lightweight solution that can effectively load an external HTML file into a page using only vanilla JavaScript. The external file contains HTML, CSS, and JS. Essentially, I want to create a concise JS snippet that loads a butt ...