Comparing JSON arrays in Typescript: A comprehensive guide

I'm currently facing an issue when trying to compare the array from a JSON file within a TypeScript function. The following code is in index.ts: Remember not to hard-code references to context variables like 'Profession'. Conditions can be nested at various levels. Try converting the condition into postfix-notation for easier evaluation.

import conditionInput from "./condition.json";

/**
 * Evaluate a condition against the context.
 * @param condition A DSL JSON object.
 * @param context An object of key-value pairs
 * @return boolean
 */
function evaluate(
  condition: typeof conditionInput,
  context: { [key: string]: string | undefined }
): boolean {
  // Your task is to implement this function to evaluate the imported condition.json with the given context. Variables prefixed with '$' should fetch their values from the context.
  // Hint 1: Do not hard-code references to context variables like 'Profession'
  // Hint 2: Conditions can be nested, n-levels deep
  // Convert the condition into postfix-notation
  
  // Ideally, one value must remain in the result stack with the last operation's result
  return false;
}

/**
 * Click "run" to execute the test cases, which should pass after your implementation.
 */
(function () {
  const cases = [
    {
      context: {
        State: "Alabama",
        Profession: "Software development",
      },
      expected: true,
    },
    {
      context: {
        State: "Texas",
      },
      expected: true,
    },
    {
      context: {
        State: "Alabama",
        Profession: "Gaming",
      },
      expected: false,
    },
    {
      context: {
        State: "Utah",
      },
      expected: false,
    },
    {
      context: {
        Profession: "Town crier",
      },
      expected: false,
    },
    {
      context: {
        Profession: "Tradesperson",
      },
      expected: true,
    },
  ];

  for (const c of cases) {
    const actual = evaluate(conditionInput, c.context);
    console.log(actual === c.expected ? "yay :-)" : "nay :-(");
  }
})();

The content of condition.json:

[
  "OR",
  [
    "AND",
    ["==", "$State", "Alabama"],
    ["==", "$Profession", "Software development"]
  ],
  ["AND", ["==", "$State", "Texas"]],
  ["OR", ["==", "$Profession", "Tradesperson"]]
]

Answer №1

function isConditionalOperator(toVerify) {
    switch (toVerify) {
        case 'AND':
        case 'OR':
            return true;
        default:
            return false;
    }
}

function isLogicalOperator(toCheck) {
    switch (toCheck) {
        case '==':
        case '<':
        case '>':
        case '<=':
        case '>=':
        case '!=':
            return true;
        default:
            return false;
    }
}

function calculate(a, operator, b) {
    return operator(a, b);
}

function symbolToOperator(symbol) {
    switch (symbol) {
        case '==': return doubleEqualsFunction;
        case '<': return lessThanFunction;
        case '>': return greaterThanFunction;
        case '>=': return lessThanOrEqualFunction;
        case '<=': return greaterThanOrEqualFunction;
        case '!=': return notEqualFunction;
        case 'OR': return orFunction;
        case 'AND': return andFunction;
    }
}

function andFunction(a, b) {return a && b; }
function orFunction(a, b) { return a || b; }
function notEqualFunction(a, b) { return a != b; }
function doubleEqualsFunction(a, b) { return a == b; }
function lessThanFunction(a, b) { return a < b; }
function greaterThanFunction(a, b) { return a > b; }
function lessThanOrEqualFunction(a, b) { return a <= b; }
function greaterThanOrEqualFunction(a, b) { return a >= b; }

function createPostfixNotationStack(arr: Array<any>, postfixConditionStack: Array<any>): Array<any> {
    arr.push(arr.shift());
    arr.forEach((element: any) => {
        if (element instanceof Array) {
            makePostfixNotationStack(element, postfixConditionStack);
        } else if ((element == 'OR' || element == 'AND') && arr.length > 2) {
            postfixConditionStack.push(element);
        } else if (arr.length == 3) {
            postfixConditionStack.push(element);
        }
    });
    return postfixConditionStack;
}


/**
 * Evaluate a condition against the context.
 * @param condition A domain-specific language (DSL) JSON object.
 * @param context An object of keys and values
 * @return boolean
 */
function assess(
    postfixConditionStack: Array<string>,
    context: { [key: string]: string | undefined }
    // count=0
): boolean {
    let postfixExecutionStack: any[] = ['|'];

    postfixConditionStack.forEach(function (current) {
        if (isLogicalOperator(current)) {
            let a = postfixExecutionStack.pop();
            let b = postfixExecutionStack.pop();
            let operator = symbolToOperator(current);
            if (typeof b == "string") {
                b = context[b.substring(1)];
            }
            postfixExecutionStack.push(
                compute(a, operator, b)
            );
        } else if (isConditionalOperator(current)) {
            let operator = symbolToOperator(current);

            postfixExecutionStack[postfixExecutionStack.length - 2] == '|' ? postfixExecutionStack.pop() : null;
            while (postfixExecutionStack[postfixExecutionStack.length - 2] != '|') {
                let a = postfixExecutionStack.pop();
                let b = postfixExecutionStack.pop();
                if (typeof b == "string") {
                    b = context[b.substring(1)];
                }
                postfixExecutionStack.push(
                    compute(a, operator, b)
                );
            };
            postfixExecutionStack[postfixExecutionStack.length - 2] != '|' ? postfixExecutionStack.push('|') : null;
        } else {
            postfixExecutionStack.push(current);
        }
    });

    return postfixExecutionStack[1];
    
    // Ideally, one value must remain in the result stack with the last operation's result
    //   return false;
}

/**
 * Click "run" to execute the test cases, which should pass after your implementation.
 */
(function () {
    const cases = [
        {
            context: {
                State: "Alabama",
                Profession: "Software development",
            },
            expected: true,
        },
        {
            context: {
                State: "Texas",
            },
            expected: true,
        },
        {
            context: {
                State: "Alabama",
                Profession: "Gaming",
            },
            expected: false,
        },
        {
            context: {
                State: "Utah",
            },
            expected: false,
        },
        {
            context: {
                Profession: "Town crier",
            },
            expected: false,
        },
        {
            context: {
                Profession: "Tradesperson",
            },
            expected: true,
        },
    ];

    let conditionInput = [
        "OR", [
            "AND", ["==", "$State", "Alabama"],
            ["==", "$Profession", "Software development"]
        ],
        ["AND", ["==", "$State", "Texas"]],
        ["OR", ["==", "$Profession", "Tradesperson"]]
    ];

    let postfixConditionStack: string[] = makePostfixNotationStack(conditionInput, []);
    
    for (const c of cases) {
        const actual = evaluate(postfixConditionStack, c.context);
        console.log(actual === c.expected ? "yay :-)" : "nay :-(");
    }
})();

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 to implementing angularjs app.service and $q in typescript

I am fairly new to TypeScript and AngularJS and I am struggling to find the correct answer for my issue. Below is the relevant code snippet: export class SidenavController { static $inject = ['$scope', '$mdSidenav']; constructor(p ...

The attempt to establish a WebSocket connection to 'wss://******/socket.io/?EIO=4&transport=websocket&sid=T2Sf_4oNIisxKLwsAAAK' was unsuccessful

I'm experiencing an issue while setting up a WebSocket connection using socket.io. When I attempt to log in, the following error message is displayed: WebSocket connection to 'wss://******/socket.io/?EIO=4&transport=websocket&sid=T2Sf_4oN ...

Double quotes (") are included in the JSONEncoder output when the input is a Python list containing strings

Currently, I am parsing a text file by splitting it on \n and storing the outcomes in a Python list. Subsequently, when using JSONEncoder().encode(mylist), the output leads to errors due to generating JavaScript code like: var jslist = [&#34;Lis ...

Maintaining the functionality of an AJAX web page even after extended periods of inactivity

When using my one-page web app, I sometimes leave the page open overnight and find that when I come back in the morning, things don't work as they should. It seems like Javascript is acting up - edit-in-place loads incorrect data, ajax calls fail to f ...

Creating a custom useStorage hook to easily save a Set data type in local storage

I attempted to make modifications to the code found at this reference link: useLocalStorage hook my goal was to enable saving a Set() to localStorage. useLocalStorage.js import { useState, useEffect } from "react"; // Custom Hook export const ...

Update two distinct object properties using a singular reference in Vue's set method

I'm facing an issue while trying to insert an object into an array using the Vue.set function. The problem is that it adds the item to a different object with the same array property. Here's a snippet of my code: data() { return { ... ...

utilizing a spacemouse in conjunction with autodesk forge

Recently, I acquired a 3dconnexion spacemouse and have been attempting to configure it to work with the forge viewer. Fortunately, I came across some JS samples in the SDK for three.js that worked flawlessly. It seems both forge and three.js utilize webgl ...

Clearly defining the data types for static dictionary values, while also deducing the precise structure or at least the keys

My goal is to create a static dictionary that is defined as a single object literal. I want to: Specify the type of values explicitly for typechecks and IDE suggestions Still have the ability to infer the exact shape, or at least keys I can achieve the f ...

Modify the height using JavaScript and then revert back to the initial CSS height

Looking for assistance with a JavaScript issue that I'm currently facing. Q1: Javascript Function to Return Image Height and Margin My website layout consists of a horizontal scroll of smaller images arranged in a grid, each with different height pe ...

The ngTable feature in AngularJS fails to initiate the getData function when making an HTTP request

I am currently working on integrating ngTable with AngularJS. After successfully installing all necessary Angular dependencies, everything seems to be functioning well. However, I am encountering an issue where my HTTP GET request is not triggering as ex ...

Is TypeScript declaration merging not functioning properly?

Trying to enhance an existing interface with a new member is causing Typescript errors for me. // foo.js export interface IOption { xOffset: number } import {IOption} from 'foo'; // Attempting to extend IOption with `yOffset`, but encounter ...

What are the methods to alter validation for a Formfield based on the input from other Formfields?

My aim is to create a Form where input fields are required only if one or more of them are filled out. If none of the fields have been filled, then no field should be mandatory. I came across a suggestion on a website that recommended using "valueChanges" ...

Test condition for the existence of field

I'm faced with a situation where I have two input styles that are very similar, and I need to create a Jolt spec that can handle both formats consistently. Here is input style 1: { "creationTime": 1503999158000, "device": { "ip": "15 ...

Utilizing Angular 2: Implementing a template-driven form to send data from a chosen element to the submitting object

Hey there! I'm fairly new to Angular 2 and have been trying to tackle this issue for a while now. I have a user object that contains another nested object, defined by the User interface: export interface UserModel{ name: string, service: Service ...

What could be the reason for the malfunction of Bootstrap Js in my template?

This question focuses on understanding how something works rather than just fixing it. I really enjoy learning about this. Currently, I am involved in a project that combines VueJS and Symfony. One of the things I would like to achieve is using Bootstrap ...

Creating a cross-platform file writer with PHP and JavaScript

My current challenge involves using buttons on an HTML page to trigger a PHP program that writes to a text file. Despite receiving a success message from my Ajax function, the file that should have been written to doesn't exist. Here's a snippet ...

Add a library to a server with npm installation

When needing to incorporate a library like Croppie, the installation process involves using npm or Bower: npm install croppie bower install croppie Given that I am working on a server, I'm uncertain where to install it. Should it be on the server it ...

Tips on using AJAX to upload serialized posts:1. Serialize the post

I'm using a form for file upload: <form method="post" id="edit_form" onsubmit="return edit(this.id);" enctype="multipart/form-data"> <input type="file" name="thumb" /> <input type="submit" value="Upload" /> </form> a ...

Regular expression ignores the initial "less than" character

Question Statement: From: John Doe <<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ddb7b2b5b3aeb0b4a9b59dbab0bcb4b1f3beb2b0">[email protected]</a>> Date: Mon, 25 Oct 2021 09:30:15 -0400 Message-ID: << ...

Footer content is displayed at the center of the page before anchoring itself to

Looking for some assistance here. Every time I refresh the page or open it anew, the footer oddly pops up in the middle before swiftly moving back down to the bottom where it belongs. It's quite bothersome and despite my best efforts, I haven't b ...