How can I efficiently extract and process JSON data with different levels of nesting in order to conduct simple computations?

I'm relatively new to the world of JavaScript and I'm currently working on a basic calculator that is able to read JSON strings and execute basic "add" or "subtract" operations based on them. At the moment, it can handle 1-level deep strings such as:

'{ op: 'add', number: 15 }'

This means that starting from an initial value of 0, it performs 0 + 15 resulting in an output of 15. However, my goal now is to enhance this functionality to process nested strings like the following, where "expr" indicates the beginning of a nested expression:

'{"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}}'

The computation for this nested string should unfold as follows: (0 - 3 = -3, -3 + (-3) = -6, -6 + (-6) = -12)

Here's the current structure of my program:

let num = 0;

class Calc {
  calc(str) {
    let object = JSON.parse(str);
    if (object.op === "add") {
      num += object.number;
    } else if (object.op === "subtract") {
      num -= object.number;
    }
    return num;
  }
}

let c = new Calc();
let exp = '{"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}}';
// console.log(c.calc(exp));

As I progress with this project, I am contemplating how to adapt this code to support processing of even more complex, deeply nested strings spanning 3, 4, or even 5 levels.

Answer №1

If your expressions always maintain the structure as you've shown, then this solution should work perfectly.

Perhaps this scenario is better suited for a recursive approach, which can be easier to grasp.

class Calculator {

    evaluateExpression(expression) {

        let temp = 0;
        if ('op' in expression) {
            if (expression.op == 'add') {
                if ('number' in expression) {
                    this.num += expression.number; 
                }
                else if ('expr' in expression) {
                    temp = this.evaluateExpression(expression.expr);
                    this.num += temp
                }
            }
            else if (expression.op == 'subtract') {
                if ('number' in expression) {
                    this.num -= expression.number; 
                }
                else if ('expr' in expression) {
                    temp = this.evaluateExpression(expression.expr);
                    this.num -= temp;
                }
            }
        }
        return this.num;
    }

    performCalculation(input) {
        let obj = JSON.parse(input);
        this.num = 0;
        return this.evaluateExpression(obj);
    }
}

fooInput = '{"op": "add", "number": 15}';
barInput = '{"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}}';

calcInstance = new Calculator();
calcInstance.performCalculation(fooInput);
calcInstance.performCalculation(barInput);

Answer №2

Greetings, I trust this information proves beneficial!

To identify the root within your nested array and track all operations, my approach would involve utilizing recurrence in a while loop. Subsequently, I would employ a for loop to streamline the solution.

data = {"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}};

var count = 0;
var ops = [];

// Identifying the location of the number while logging each operation
while (data.number == undefined) {
    ops[count] = data.op;
    data = data.expr;
    count++;
}

var num = 0; // Initial value
ops.push(data.op); // Addition operation with the number
number = data.number; // The target number

// Retroactively computing the result
for (var i = 0; i < ops.length; i++) {

    if (ops[ops.length - i - 1] === "add") {
        num += number;
    } else if (ops[ops.length - i - 1] === "subtract") {
        num -= number;
    }

    number = num;
}

console.log(num);

Nevertheless: I recall one of my instructors advising against the use of while loops in production code... but while serves a purpose as any other tool should be properly utilized 😄

Answer №3

I think utilizing recursive methods can offer a solution to this particular issue. I hope this suggestion proves beneficial!


let expression = '{"op": "multiply", "expr" : {"op" : "multiply", "expr" : {"op" : "divide", "number" : 6}}}';
const multiplyOperation = 'multiply';
const divideOperation = 'divide';

class MathSolver {
    solveEquation(inputString){

    let objectData = JSON.parse(inputString);
    let previousResult = 0;

        function performOperation(obj){

            if(obj == undefined){
                return 0;
            }
            let temporaryValue = performOperation(obj.expr);
            if(obj.hasOwnProperty('number') == true){
                previousResult = obj['number'];
            }
            if(obj.op == multiplyOperation){
                previousResult *= temporaryValue;
            }
            if(obj.op == divideOperation){
                previousResult /= temporaryValue;
            }
            return previousResult;

        }
        return performOperation(objectData);
        }
}

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

Passing an array as an argument to a pointer in C

I am encountering an issue with the code below: void getPossibilities(int *rating[200][3]){ // do something } int main () { int rating[200][3]; getPossibilities(&rating); } When I run this code, I receive the following error message: error: canno ...

What is the importance of including parentheses when passing a function to a directive?

Hello, I'm currently a beginner in Angular and I am experimenting with directives. Here is the code snippet that I am using: HTML <div ng-app="scopetest" ng-controller="controller"> <div phone action="callhome()"> </div> </div ...

Tips for including absent items in an array

Looking to fill in missing weeks and years in an array of objects that have a reportYear and reportWeek property. How can I insert additional objects to cover all weeks from the beginning date to the end date? For example: Input: [ {"reportYear":2017, ...

Update a div container using jQuery

Hey there, I need some help with a specific part of my code snippet: <div class="tags-column" id="tags"> <h2>Tags</h2> <ul> <% @presenter.tag_counters.each do |tag_counter| %> <li class=" ...

Exploring the depths of asynchronous calls in AngularJS with nested functions

Currently, I'm tackling a small project with AngularJS and finding myself tangled in multiple asynchronous calls that are starting to become chaotic. I know there must be a more efficient way to handle these calls, but I'm unsure of the best appr ...

What information is displayed on the visible class roster?

I'm feeling a bit lost with this. element.classList.add('visible'); Can someone clarify what the 'visible' in this code snippet is? Is it an event or something else? Appreciate your help! ...

The event is eagerly anticipating the AJAX call despite the asynchronous setting being true

I'm implementing a feature where the user can open a new tab to continue using the system while the current tab is busy making a request to the server. To achieve this, I am trying to utilize $(window).load() or $(window.document).ready() to automati ...

Tips for keeping components mounted despite changes in the path

How can I maintain state in React routes to prevent unmounting when switching between them? In my application, it's crucial to keep the state intact during route changes. When changing routes, the respective components mount and unmount. How can this ...

What are the steps to deploy Next JS?

For my latest project, I dived into the world of Next JS with Tailwind CSS and decided to use "next build" to compile it. However, after running the command, it generated a folder named ".next", but surprisingly no .html files were found within. Coming fr ...

Loop through a SimpleXMLElement array and save each element to its own text file

I've encountered a challenge that has me stumped. I have an array of SimpleXMLElement objects containing PDF data bytes. My goal is to loop through the array, writing each chunk of PDF data bytes to separate text files so that I can later convert them ...

Incorporate a pair of additional columns and showcase the outcome within a third column within an HTML

function = () => { var info1 = parseInt(document.getElementById("info1").value); var info2 = parseInt(document.getElementById("info2").value); var res = Number(info1.value + info2.value); var info3 = document.getElementById("info3"); ...

Integrating chat functionality with a structured data format

Considering creating a collaborative communication platform, I am contemplating whether to develop a comprehensive application in JavaScript with MVC architecture or utilize it solely for managing message delivery using Node.js and socketIO. Would it be m ...

Tips for navigating between slides on a CSS carousel?

I am currently in the process of creating a CSS-based carousel .carousel { -webkit-scroll-snap-type: x mandatory; -ms-scroll-snap-type: x mandatory; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; overflow-x: scro ...

Requesting data with Ajax: utilizing parameters in the format of x-www-form-urlencoded

When adding parameters to a get/post request, it is important to encode them in application/x-www-form-urlencoded form. Is it necessary to encode values each time? Does JavaScript provide a method for encoding values? What options are available for caching ...

Traverse a JSON array containing numerous results

Trying to find a solution for parsing a JSON response with multiple results is my current task. Below is the data I received as a response: Array ( [id] => 7181676 [api_request_id] => 20984853 [user] => 8305 [vin] => JTDKN3DU ...

Equivalent of window.onkeypress in Typescript and NodeJS

Can someone help me figure out how to accomplish the following: document.addEventListener('keypress', (event) => { // Need this function to trigger whenever a key is pressed }); in a node.js environment using TypeScript or JavaScript? ...

Exploring Vue Routing with Regular Expressions

Recently, I integrated a route with a parameter in my Vue project. const routes = [ { path: "/:lang(^$|^es$|^pt$|^cn$)", name: "Home", component: Page, }, { path: "/privacy", name: "Privacy", component: Privacy, }, { ...

Whenever I try to access my Node.js API from Heroku's live server, I encounter a CORS policy error

Whenever I try to access my Node.js API from the Angular app (running on a local setup) and host the API on Heroku's live server, I encounter the following error: CORS policy: No 'Access-Control-Allow-Origin'. Interestingly, when I host the ...

The responses stored within the array should remain intact and not vanish

I am facing a challenge with a basic exercise I am working on. The exercise involves allowing visitors to ask a random question, and in return, they receive a random answer from an array. I wish to retain the questions and their corresponding answers. I w ...

Display more/hide less form using div elements in a NextJS project

Looking to create a hidden block of amenities on my hotel website that can be expanded and collapsed with buttons in NextJS using tailwind-css. How can I achieve this functionality? Example 1: https://i.stack.imgur.com/BbrUj.png Example-2: https://i.stac ...