0

I'm pretty new to JS and am trying to work on a basic calculator that reads in JSON strings and performs basic "add" or "subtract" operations on them. Currently, it can process 1-level deep strings like so:

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

Where the initial value is 0 and will perform 0+15 so the output is 15. What I am trying to do now, is make the same function process a nested string like so where "expr" denotes that start of a nested expression:

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

And the operation should go like this: (0-3= -3, -3+-3= -6, -6+-6= -12)

My current program is as follows:

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));

How can I modify this to further handle even 3,4,5 levels nested strings?

Tony
  • 77
  • 3
  • 12
  • Using recursion. Also note that the first string you posted isn't valid JSON. Also why are you using a class that has a single method that doesn't reference `this` but does modify a global variable? Just make it a function. – Jared Smith Sep 07 '19 at 01:10
  • How is it not valid, it processes it just fine. And I need it in its own class for requirement's sake. Also, what would I pass in for the recursion? – Tony Sep 07 '19 at 01:28
  • umm...`'{ op: 'add', number: 15 }'` isn't valid JSON. It isn't even a valid Javascript string (SO's syntax highlighting should have tipped you off to that). If you replace one of the sets of single quotes with doubles to fix that, feeding it to JSON parse will throw an error, because your property names and strings aren't double-quoted. If it sounds like I'm being nitpicky it's because I am, and I am because computers are quite nitpicky. – Jared Smith Sep 07 '19 at 01:58
  • Possible duplicate of [Iterate through Nested JavaScript Objects](https://stackoverflow.com/questions/8085004/iterate-through-nested-javascript-objects) – Jared Smith Sep 07 '19 at 02:00

3 Answers3

0

Hey there, I hope this helps!

I would use recurrence in a while loop to find where is your root and capturing all operation as we move inside your nested array. After that I would use a for loop to consolidate the answer.

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

var count = 0;
var operation = [];

// finding where is the number and logging all operations up to this point
while (string.number == undefined) {
    operation[count] = string.op;
    string = string.expr
    count++;
}

var num = 0; // starting num
operation.push(string.op); // add number operation
number = string.number; //this is the num that we need to work with


// now we just need to work backwards
for (var i = 0; i < operation.length; i++) {

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

    number = num;
}

console.log(num);

that being said: I do remember one of my professors saying "never ever use a while loop in your production code"... but while is a tool and if its a tool let's use it

costargc
  • 516
  • 5
  • 14
0

In case your expressions will always keep the form like you posted this should work.

Maybe this is a case where a recursive approach is simpler to understand.

class Calc {

    evaluate(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.evaluate(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.evaluate(expression.expr);
                    this.num -= temp;
                }
            }
        }
        return this.num;
    }

    calc(str) {
        let object = JSON.parse(str);
        this.num = 0;
        return this.evaluate(object);
    }
}

foo = '{"op": "add", "number": 15}';
bar = '{"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}}';

c = new Calc();
c.calc(foo);
c.calc(bar);
elmo26
  • 150
  • 8
0

I believe you can use recursion to solve problem. Hope it helps!!


let exp = '{"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}}';
const addNumber = 'add';
const subtractNumber = 'subtract';

class Calculator {
    calculate(str){

    let object = JSON.parse(str);
    let prevSum = 0;

        function traverseObject(object){

            if(object == undefined){
                return 0;
            }
            let temp = traverseObject(object.expr);
            if(object.hasOwnProperty('number') == true){
                prevSum = object['number'];
            }
            if(object.op == addNumber){
                prevSum += temp;
            }
            if(object.op == subtractNumber){
                prevSum -= temp;
            }
            return prevSum;

        }
        return traverseObject(object);
        }
}
tlrmacl
  • 51
  • 1