从数组创建布尔值、数组和对象的嵌套对象

Create nested object of booleans, arrays and objects from array

我正在尝试创建一个对象来满足 json-logic-js 所需的结构。下面提供了该结构的示例。

源数组由booleansstrings组成。字符串只能是 ORANDNANDNOR。现在我只使用 ORAND.

布尔值和字符串数组可能如下所示。这些值是动态的。所以布尔值可以是 true 或 false 以及如上所述的字符串。

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

如果这个源数组在 if 语句中,我认为它的分组如下:

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

我希望输出满足 json-logic-js JS 包的以下对象:

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

我已经尝试过递归函数并一直在使用 .reduce() 方法,但仍然无法找到解决方案。当我遍历源数组时,我很难创建对象。我在 SO 上搜索了类似的答案,但 none 似乎想要与我相同的结果对象结构。

尝试以下解决方案。希望代码或多或少是 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));