Как я могу скомпилировать и оценить логические операторы и операнды, указанные в объекте?

#javascript #parsing #ecmascript-6 #boolean-logic

#javascript #Синтаксический анализ #ecmascript-6 #boolean-logic

Вопрос:

Есть ли компилятор или простой способ, которым я могу скомпилировать и оценить логические операторы и операнды, указанные в объекте. Это похоже на операторы mongodb $or и $and. Например:

 return {
  $or: [
    foo: [...],
    bar: [...]
  ]
}
  

Когда компилятор обнаружит foo , он вызовет соответствующую функцию со значением, предоставленным для того же самого. То же самое касается bar . Затем будут logical OR получены результаты двух операций. Я хочу обрабатывать операторы $and и $or . Я бы выполнил простые проверки для такого простого примера, но я хочу иметь возможность вкладывать логические операторы. Сложный пример:

 return {
  $or: [
    { 
      $and: [
        { foo: [...] }, 
        { bar: [...] }
      ] 
    }, 
    { baz: [...] }, 
    () => m < n
  ]
}
  

Упрощенное определение foo , bar и baz :

 export const evalFoo = items => {
  return items.indexOf("foo") >= 0;
};

export const evalBar = items => {
  return items.indexOf("bar") >= 0;
};

export const evalBaz = items => {
  return items.indexOf("baz") >= 0;
};
  

Пример данных:

Установите 1

 m = 4; n = 1; foo: ['foo', 'x']; bar: ['bar', 'y']; baz: ['baz', 'z']

RESULT = true; // because $and results to true.
  

Установите 2

 m = 4; n = 1; foo: ['x']; bar: ['y']; baz: ['x']

RESULT = false; // because m > n and $and results to false.
  

Установите 3

 m = 1; n = 3; foo: ['x']; bar: ['y']; baz: ['x']

RESULT = true; // because m < n.
  

Установите 4

 m = 3; n = 1; foo: ['x']; bar: ['bar']; baz: ['z']

RESULT = true; // because m > n, baz() is false and x and $and is false.
  

Комментарии:

1. пожалуйста, добавьте также некоторые данные и желаемый результат. какую функцию вы вызываете для элементов foo или bar ? каково содержимое массивов?

2. Нет, для этого нет «компилятора» или около того. Однако вы можете легко реализовать это самостоятельно, (рекурсивно) перечислив объект и вызвав свои функции, когда вы сталкиваетесь с таким ключом. Вы что-нибудь пробовали?

3. Я еще ничего не пробовал. Подумал, что было бы лучше обратиться за помощью, прежде чем пытаться изобретать велосипед.

4. @MutaiMwiti Нет, вы не изобретаете колесо заново или, по крайней мере, ничего такого фундаментального, как колесо. Я сомневаюсь, что существует библиотека, которая делает именно то, что вы хотите, и даже если бы тогда был запрос на нее, это не по теме в StackOverflow. Пожалуйста, покажите нам вашу попытку, решение — довольно простая рекурсивная функция.

Ответ №1:

Вы могли бы взять что-то вроде этого, где вы проводите различие между $and и $or или функциями.

Это работает, принимая объект с ключами для методов массива, таких как Array#every , который действует как логический, и путем проверки значений в объекте и возврата, true если все элементы с их обратными вызовами возвращают истинное значение. Аналогично работает Array#some , но необходим только один элемент, обратный вызов которого возвращает истинное значение.

Другой объект содержит функции и позволяет получить к ним доступ с помощью ключа.

Первый параметр проверяет, является ли параметр функцией, и если да, то возвращает результат вызова.

Затем параметр получает проверку, и если он ложный, например null , или если значение не является объектом, функция завершается на false .

Для получения пары ключ / значение выполняется деструктирующее присваивание с первой записью из объекта.

Если key находится в объекте operator, значение берется как метод для повторения value и возвращается.

Если key находится в объекте functions, то функция вызывается с value в качестве параметра и возвращается.

Наконец, возвращается false , потому что никакая другая проверка не была истинной, и условие не может быть разрешено.

 function evaluate(object) {
    var operators = { $or: 'some', $and: 'every' },
        fns = {
            foo: items => items.indexOf("foo") >= 0,
            bar: items => items.indexOf("bar") >= 0,
            baz: items => items.indexOf("baz") >= 0
        },
        key,
        value;

    if (typeof object === 'function') return object();
    if (!object || typeof object !== 'object') return false;

    [key, value] = Object.entries(object)[0];

    if (key in operators) return value[operators[key]](evaluate);
    if (key in fns) return fns[key](value);
    return false;
}

var m = 4,
    n = 1,
    object = {
        $or: [
            {
                $and: [
                    { foo: ['foo', 'x'] },
                    { bar: ['bar', 'y'] }
                ]
            },
            { baz: ['baz', 'z'] },
            () => m < n
        ]
    },
    result = evaluate(object);

console.log(result);  

Комментарии:

1. этот ответ работает. Не могли бы вы разобрать это?

2. Пожалуйста, объясните эту строку: if (key in operators) return value[operators[key]](evaluate); .

3. он проверяет, есть ли в объекте key , like $or , operators и если это так true , то массив value вызывается с помощью key of operators , like some или every с обратным вызовом функции evaluate . вложенные объекты передаются функции, а результат true / false принимается за квантор.