Home > Enterprise >  Create nested object of booleans, arrays and objects from array
Create nested object of booleans, arrays and objects from array

Time:02-11

I am trying to create an object to satisfy the structure required by json-logic-js. An example of that structure is provided below.

The source array is made up of booleans and strings. Strings can only be OR, AND, NAND or NOR. For now am I working only with OR and AND.

The array of booleans and strings might look like the below. The values are dynamic. So the booleans can be either true or false and strings as mentioned above.

const source = [false, "OR", false, "OR", false, "AND", false, "AND", false, "OR", true]

The grouping of this source array if it were in an if statement would I believe be as follows:

(false || false || (false && false && false) || true) // true

And I would expect to output the following object which satifies the json-logic-js JS package:

const result = {
    'or': [
        false,
        false,
        {
            'and': [
                false,
                false,
                false,
            ]
        },
        true,
    ]
}

I have tried recursive functions and have been playing with the .reduce() method but as have yet been unable to find a solution. I struggle creating the object as I iterate over the source array. I have searched for similar answers here on SO but none seem to want the same result object structure as I do.

CodePudding user response:

Try the following solution. Hopefully the code is more or less self-explanatory:

function process(arr) {
  const isBool = (x) => x === true || x === false;
  const prec = (x) => -["AND", "OR"].indexOf(x);

  // Convert infix -> postfix
  const postfix = [];
  const ops = [];
  for (const x of arr) {
    if (!isBool(x)) {
      const prev = ops[ops.length - 1];
      if (prev === undefined || prec(x) > prec(prev)) {
        ops.push(x);
      } else {
        while (ops.length > 0 && prec(x) < prec(ops[ops.length - 1])) {
          postfix.push(ops.pop());
        }
        ops.push(x);
      }
    } else {
      postfix.push(x);
    }
  }
  postfix.push(...ops.reverse());

  // Convert postfix -> output format
  const stack = [];
  for (const x of postfix) {
    if (!isBool(x)) {
      const op = x.toLowerCase();
      const prevs = [stack.pop(), stack.pop()];
      const obj = prevs.find((y) => !isBool(y) && y.hasOwnProperty(op));
      if (obj !== undefined) {
        const other = prevs.find((y) => y !== obj);
        obj[op].push(other);
        stack.push(obj);
      } else {
        stack.push({
          [op]: prevs,
        });
      }
    } else {
      stack.push(x);
    }
  }
  return stack[0];
}

console.log(JSON.stringify(process([false, "OR", false, "OR", false, "AND", false, "AND", false, "OR", true]), null, 2));

  • Related