Recursive function to format nested arrays to match against arrays of conditions

Viewed 92

Trying to write this eval function that takes in cases, loops through them and needs to check if it matches to a condition in a conditions array and returns true or false. I'm not sure how best to format the conditions array and run the matching on it. Conditions are nested, n-levels deep, so trying to get a recursive function.

console.log(cases.forEach(c => eval(formattedCondition, c.item)))

const conditions = [
 "OR",
 ["AND",["==","maker","airbus"],["==","name","A320"]],
 ["AND",[ "==", "maker","boeing"]],
 ["OR",["==","name","B767"]]
]

const cases = [
 {
   "item": {
    'maker': 'airbus',
    'name':"A320",
   }
 // should return true for this case
 },
 {
   "item": {
    'maker': 'embraer',
    'name':"e175",
   }
 // should return false for this case
 },
 {
   "item": {
    'maker': 'boeing',
   }
 // should return true for this case
 },
 {
   "item": {
    'name':"B767",
   }
// should return true for this case
 },
 {
   "item": {
    'maker': 'boeing',
    'name':"B777",
   }
 // should return false for this case
 },
]
1 Answers

You could take an approach without eval and use the data to build expressions with a function for checking with equal and some quantizers for AND and OR.

const
    conditions = ["OR", ["AND", ["==", "maker", "airbus"], ["==", "name", "A320"]], ["AND", ["==", "maker", "boeing"]], ["OR", ["==", "name", "B767"]]],
    take = object => {
        const
            quantifiers = { AND: 'every', OR: 'some' },
            operators = { '==': (a, b) => a == b },
            evaluate = ([symbol, ...values]) => values.every(v => typeof v === 'string')
                ? operators[symbol](object[values[0]], values[1])
                : values[quantifiers[symbol]](evaluate);
        return evaluate;
    },
    cases = [
        { item: { maker: 'airbus', name: "A320" } },    // true
        { item: { maker: 'embraer', name: "e175" } },   // false
        { item: { maker: 'boeing' } },                  // true
        { item: { name: "B767" } },                     // true
        { item: { maker: 'boeing', name: "B777" } },    // true instead of false
    ],
    result = cases.map(({ item }) => take(item)(conditions));

console.log(result);

Related