Calculating the sum of values in a JSON array using a specific parameter in Typescript

A flat JSON array contains repetitive identifier, categoryId, and category:

    data: [
    {
        "identifier": "data",
        "categoryId": "1",
        "category": "Baked goods",
        "product": "Aunt Hattie's",
        "price": "375"
    },
    {
        "identifier": "data",
        "categoryId": "1",
        "category": "Baked goods",
        "product": "Back to Nature",
        "price": "343"
    },        
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Mars Muffin (McVitie's)",
        "price": "465"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "McVitie's",
        "price": "251"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Mr Kipling",
        "price": "260"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Mr Kipling Frosty Fancies",
        "price": "210"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Amul",
        "price": "474"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Borden",
        "price": "184"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Broughton Foods Company",
        "price": "43"
    },
]

To calculate the total price for each category and add a new object at the end of each category with the identifier set as Total along with the total value, you can use the following sorting function:

function compare(a,b) {
  if (a.categoryId < b.categoryId)
  return -1;
  if (a.categoryId> b.categoryId)
  return 1;
 return 0;
}

data.sort(compare);

UPDATED OUTPUT FORMAT

The desired output format is as follows:

: [
    {
        "identifier": "data",
        "categoryId": "1",
        "category": "Baked goods",
        "product": "Aunt Hattie's",
        "price": "110"
    },
    {
        "identifier": "data",
        "categoryId": "1",
        "category": "Baked goods",
        "product": "Back to Nature",
        "price": "344"
    },
    {
        "identifier": "Total",
        "categoryId": "1",
        "category": "Baked goods",
        "price": "454"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Mars Muffin (McVitie's)",
        "price": "455"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Secret Recipe",
        "price": "471"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Vimto Jam Tarts",
        "price": "235"
    },
    {
        "identifier": "Total",
        "categoryId": "2",
        "category": "Cakes",
        "price": "1161"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Alta Dena",
        "price": "158"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Chivers",
        "price": "399"
    },
    {
        "identifier": "Total",
        "categoryId": "3",
        "category": "Dairy products",
        "price": "557"
    }
]

Answer №1

Using a hashtable for referencing the same categories and adding another object for each total group is one approach.

All totals are now included at the end of the data set.

To sort the data with the top items first and the totals at the bottom of each category, you can implement a check for the total and move that part to the end of the category section.

var data = [{ identifier: "data", categoryId: "1", category: "Baked goods", product: "Aunt Hattie's", price: "375" }, { identifier: "data", categoryId: "1", category: "Baked goods", product: "Back to Nature", price: "343" }, { identifier: "data", categoryId: "2", category: "Cakes", product: "Mars Muffin (McVitie's)", price: "465" }, { identifier: "data", categoryId: "2", category: "Cakes", product: "McVitie's", price: "251" }, { identifier: "data", categoryId: "2", category: "Cakes", product: "Mr Kipling", price: "260" }, { identifier: "data", categoryId: "2", category: "Cakes", product: "Mr Kipling Frosty Fancies", price: "210" }, { identifier: "data", categoryId: "3", category: "Dairy products", product: "Amul", price: "474" }, { identifier: "data", categoryId: "3", category: "Dairy products", product: "Borden", price: "184" }, { identifier: "data", categoryId: "3", category: "Dairy products", product: "Broughton Foods Company", price: "43" }],
    i,
    l = data.length,
    hash = Object.create(null),
    categoryId, category, price;

for (i = 0; i < l; i++) {
    ({ categoryId, category, price } = data[i]);
    if (!(categoryId in hash)) {
        hash[categoryId] = { identifier: "total", categoryId, category, price: 0 };
        data.push(hash[categoryId]);
    }
    hash[categoryId].price += +price;
}

data.sort((a, b) =>
    a.categoryId - b.categoryId
        || (a.identifier === 'total') - (b.identifier === 'total')
);

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

Answer №2

Give this a shot!

var data = [
    {
        "identifier": "data",
        "categoryId": "1",
        "category": "Baked goods",
        "product": "Aunt Hattie's",
        "price": "375"
    },
    {
        "identifier": "data",
        "categoryId": "1",
        "category": "Baked goods",
        "product": "Back to Nature",
        "price": "343"
    },        
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Mars Muffin (McVitie's)",
        "price": "465"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "McVitie's",
        "price": "251"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Mr Kipling",
        "price": "260"
    },
    {
        "identifier": "data",
        "categoryId": "2",
        "category": "Cakes",
        "product": "Mr Kipling Frosty Fancies",
        "price": "210"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Amul",
        "price": "474"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Borden",
        "price": "184"
    },
    {
        "identifier": "data",
        "categoryId": "3",
        "category": "Dairy products",
        "product": "Broughton Foods Company",
        "price": "43"
    },
]

var total= 0;
var element = {};
data = data.sort((a,b)=> a.categoryId - b.categoryId)
var result = [];
data.forEach((ele,index)=>{
     
    if(!element.categoryId || element.categoryId == ele.categoryId){
        result.push(ele);
        total += parseInt(ele.price);
    }else{
      result.push({
           "identifier": "total",
           "categoryId": element.categoryId,
           "category": element.category,
           "total" : total
      });
      result.push(ele);
      total = parseInt(ele.price);  
    }
   element = ele;
})
result.push({
  identifier  :element.identifier,
  total : total
});
console.log(result);

Answer №3

To get the result you want, employ Array.reduce in conjunction with a hash object to compute the overall cost:

Check out this Stackblitz demo

Answer №4

Here is an alternative solution to the problem.

const sortedData = data.sort((item1, item2) => item1.categoryId - item2.categoryId)
.reduce((result, item) => {
    const { category, categoryId } = result.last
    const isEnd = categoryId && categoryId !== item.categoryId;
    const total = isEnd ? [{ category, categoryId, 'identifier': 'Total', 'price': result.sum }] : [];
    return {
      list: [...result.list, ...total, item],
      sum: (!isEnd ? result.sum : 0) + parseInt(item.price),
      last: item
    };
}, { list: [], sum: 0, last: {} });

Try it out on stackblitz

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

Add a CSS class to the text that is selected within a Content Editable div

Hey there, I'm having an issue where the class is being applied to the button when pressed instead of the selected text. Here's my current code: The button needs to be a div, but it might be causing the problem. I just want the highlighted text ...

Improving the pagination performance in AngularJS

I created an HTML template to showcase member details, along with adding pagination functionality to improve initial load time. Currently, I retrieve 15 members from the server at once and display them, allowing users to navigate through more members using ...

Traditional method for comparing prevProps in componentDidUpdate

As I work on prototyping, I've noticed that when new props come in as an array of complex objects, prevProps.myProp===this.props.myProp always returns false. While using JSON.stringify for comparison seems to work, it doesn't feel very reliable. ...

Can you explain the meaning behind the code Array.remove = function() {...}?

I encountered this code snippet that has left me puzzled: Array.remove = function(array, from, to) { var rest = array.slice((to || from) + 1 || array.length); array.length = from < 0 ? array.length + from : from; return array.push.apply(arr ...

What is the time complexity for finding a specific value in a two-dimensional matrix?

The challenge at hand is quite straightforward: develop an algorithm that can determine if the target value exists within the given matrix. Here, I have devised two potential solutions. However, I am uncertain as to which one would be more efficient. Perso ...

Looking for categorized posts on WordPress using the WP-API?

Is there a way to search posts by multiple categories using the WP-API? I understand that I can search posts by the attribute categories or filter[cat]. However, most posts contain more than one category. I attempted to search using different methods: ...

Tips for effectively utilizing a Query or QueryTask with local graphics (GraphicsLayer)

Working on developing an ESRI map prototype using Angular4, I have successfully utilized the Draw tool to initiate a Query on a FeatureLayer to draw various graphics such as ConvexHull and Buffer. The primary goal was to create a clear Buffer graphic over ...

Unable to access 'this' within a custom operator in RxJs

I developed a unique operator that utilizes the this keyword, but I am encountering an issue where it always returns undefined. Even though I used bind to pass this into the function. My special operator function shouldLoadNewOptimizationData() { retu ...

Twilio Group MMS feature experiencing technical difficulties

I currently have a Twilio Trial account with an active number that supports SMS/MMS. My goal is to use this number for group MMS chats, but I am facing some challenges. After following a tutorial on Tut, I attempted to create a basic test using the provid ...

Determining the type of a keyof T in Typescript

I am currently working on developing a reusable function that takes an observable and applies various operators to return another observable. One issue I am facing is getting the correct type for the value based on the use of the key. The code snippet bel ...

The event listener $(window).on('popstate') does not function properly in Internet Explorer

$window 'popstate' event is not functioning properly in IE when using the browser back button. Here is the code snippet used to remove certain modal classes when navigating back. $(window).on('popstate', function(event) { event.pre ...

What methods are available for authentication to be shared among microservices?

I am managing two distinct Node.js services. Service X handles user authentication. Once a user successfully logs in, they are directed to Service Y (which is hosted on a subdomain of the domain where Service X resides). Authentication is done using JWT. ...

Understanding the Functions of Angular Providers and Implementing Them

Just starting out with Angular and following a tutorial from this video. I decided to experiment by adding providers :[EmployeeService] to both employee-list.component.ts and empployee.component.ts within the @component section. However, this led to an err ...

Understanding how to decode querystring parameters within a Django view

In the application I'm working on, there is a search form that utilizes a jQuery autocomplete plugin. This plugin processes the querystring and sends back the suggested item using encodeURI(q). For example, an item like Johnny's sports displays ...

Importing a JSON or JSONC file into a vite/typescript project can be easily done

I am looking for a way to seamlessly share my routes between my actix-web backend and Vue with Vue-Router frontend without needing separate route files. I want to define the routes on the frontend without having to make any changes on the server side. If t ...

What is the process for integrating ng-bootstrap into an Angular 5 project?

Has anyone encountered issues loading ng-bootstrap in their Angular project? I'm experiencing difficulties and would appreciate any insights. Thank you for your help! This is my app.module.ts file: import { BrowserModule } from '@angular/platf ...

Is it possible to define data types for the global context in cucumber?

Embarking on a fresh cucumber-selenium project in Typescript, I am eager to keep the Driver in the world context. However, following the method suggested here, I encounter an issue where the Driver type remains inaccessible to step definitions. This means ...

Tips for displaying a table with a button click

I am struggling to figure out how to embed a table inside a button in order to display the table when the button is clicked and hide it when clicked again. Below is the code I have been working with: function toggleTable(){ document.getElementById ...

Mongooses provide a JSON list of tags that are defined as subdocuments

I've been struggling with a problem for the last four days. I have a schema and subdocument schema set up like this: var mongoose = require( 'mongoose' ), Schema = mongoose.Schema; var ProjectSchema = new Schema({ name: String, ...

Tips for effectively handling the Ajax success callback function

if (isset($_POST["getCanvas"]) ) { $projectName= mysqli_real_escape_string($db2, $_POST['whichProject']); $query = "SELECT objectsList FROM projectObjectstable WHERE projectName='$projectName'"; ...