Reputation: 487
Is there a compiler or an easy way I can compile and evaluate logical operators and operands specified on an object. This is to akin to mongodb $or and $and operators. For example:
return {
$or: [
foo: [...],
bar: [...]
]
}
When the compiler encounters foo
it will call a corresponding function with the value provided for the same. The same goes for bar
. It will then logical OR
the results of the two operations. I want to handle $and
and $or
operators. I would do simple checks for such a simple example but I want to have the ability to nest the logical operators. A complex example:
return {
$or: [
{
$and: [
{ foo: [...] },
{ bar: [...] }
]
},
{ baz: [...] },
() => m < n
]
}
Simplified definition of foo
, bar
and 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;
};
Sample data:
Set 1
m = 4; n = 1; foo: ['foo', 'x']; bar: ['bar', 'y']; baz: ['baz', 'z']
RESULT = true; // because $and results to true.
Set 2
m = 4; n = 1; foo: ['x']; bar: ['y']; baz: ['x']
RESULT = false; // because m > n and $and results to false.
Set 3
m = 1; n = 3; foo: ['x']; bar: ['y']; baz: ['x']
RESULT = true; // because m < n.
Set 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.
Upvotes: 3
Views: 199
Reputation: 386650
You could take something like this, where you differentiate between $and
and $or
or the functions.
It works by taking an object with the keys for array methods like Array#every
, which acts like a logical and by testing the values in an object and return true
if all items with their callbacks return a truthy value. Analogous works Array#some
, but there is only one item necessary which callback returns a truthy value.
The other object contains functions and allows to access them by using the key.
The first par checks if the parameter is a function and if so, it returns the result of the call.
Then the parameter gets a check and if falsy, like null
or if the value is not an object, the function terminates with false
.
For taking a key/value pair a destructuring assignment takes place with the first entry from the object.
If key
is in the operator object, the value is taken as method for iterating the value
and returned.
If key
is in the functions object, then the function is called with value
as parameter and returned.
Finally a false
is returned, because no other check was true and the condition can not be resolved.
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);
Upvotes: 1