#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
ofoperators
, likesome
илиevery
с обратным вызовом функцииevaluate
. вложенные объекты передаются функции, а результатtrue
/false
принимается за квантор.