skip to Main Content

I have the following JS object:

let obj = {
    b: 1,
    c: 1,
    d: 2
}

I want to write a function that takes an input array and checks whether the fields listed in this array are present in obj, but I want to have logic in the conditions. So something like

arr = ['b', 'c' || 'd']   (returns true if obj has an entry for `b`, and for either `c` or `d`)

or

arr = ['c' && 'd']   (returns true only if obj has entries for both `c` and `d`)

so in my function I imagine writing a condition like

return arr.forEach(condition => object[condition])

How can I approach this?

3

Answers


  1. You can do something like this:
    Write a finction like the checkFields function takes in the object, and a string representing the condition you want to check for example: "a||b" or "a&&b" or "a",
    it’s gonna split the string by || and && and check for the conditions and return true/false based on wether the condition istrue or not.
    Next the calcResult function will take an array like ["a||b", "a"] and pass each of the items of it to the checkFields function and return true if all of the results are true.

    const checkFields = (obj, condition) => {
      let result = false;
      if (condition.includes("||")) {
        const [field1, field2] = condition.split("||");
        if (obj.hasOwnProperty(field1) || obj.hasOwnProperty(field2)) {
          result = true;
        } else result = false;
      } else if (condition.includes("&&")) {
        const [field1, field2] = condition.split("&&");
        if (obj.hasOwnProperty(field1) && obj.hasOwnProperty(field2)) {
          result = true;
        } else result = false;
      } else {
        if (obj.hasOwnProperty(condition)) {
          result = true;
        } else result = false;
      }
    
      return result;
    };
    
    
    const obj = {
      b: 1,
      c: 1,
      d: 2
    };
    
    const arr1 = ['b', 'c', 'd||b', 'a||f'];
    const arr2 = ['b', 'c&&b', 'd&&b', 'a||d'];
    const calcResult = (array) => array.reduce((acc, item) => acc && checkFields(obj, item), true);
    
    
    console.log(calcResult(arr1));
    console.log(calcResult(arr2));
    Login or Signup to reply.
  2. Build up rules programmatically and evaluate them.

    /* library code */
    const hasProp = prop => obj =>
      prop in obj;
      
    const or = (...conditions) => obj =>
      conditions.some(condition => condition(obj));
    
    const and = (...conditions) => obj =>
      conditions.every(condition => condition(obj));
      
    const apply = rules => obj =>
      rules.map(fn => fn(obj));
    /* /library code */
    
    const arr = [
      hasProp("a"), // false
      hasProp("b"), // true
      or(hasProp("a"), hasProp("b")), // true
      or(hasProp("a"), hasProp("z")), // false
      and(hasProp("c"), hasProp("d")), // true
      and(hasProp("a"), hasProp("d")), // false
      and(hasProp("b"), hasProp("c"), hasProp("d")), // true
      and(or(hasProp("a"), hasProp("b")), and(hasProp("d"), hasProp("d"))) // true
    ];
    
    const checkAllRules = apply(arr);
    
    console.log(checkAllRules(obj));
    <script>
    //set up data
    let obj = {
        b: 1,
        c: 1,
        d: 2
    }
    </script>

    This can be extended with any amount of more checks (like if a property has a specific value, if it is a Date object) and operators (like not to invert a result):

    /* library code */
    const hasProp = prop => obj =>
      prop in obj;
      
    const hasValue = (prop, value) => obj =>
      obj[prop] === value;
    
    const isDateObject = obj =>
      obj instanceof Date;
      
    const or = (...conditions) => obj =>
      conditions.some(condition => condition(obj));
    
    const and = (...conditions) => obj =>
      conditions.every(condition => condition(obj));
    
    const not = rule => obj => 
      !rule(obj);
      
    const apply = rules => obj =>
      rules.map(fn => fn(obj));
    /* /library code */
    
    const arr = [
      hasValue("b", 1), // true
      hasValue("b", 7), // false
      isDateObject, //false
      not(hasProp("a")), //true
      or(hasValue("b", 7), hasValue("d", 2)), // true
      and(hasValue("c", 1), not(isDateObject)), // true
    ];
    
    const checkAllRules = apply(arr);
    
    console.log(checkAllRules(obj));
    <script>
    //set up data
    let obj = {
        b: 1,
        c: 1,
        d: 2
    }
    </script>
    Login or Signup to reply.
  3. You are going to have to write yourself some sort of rules engine that is able to process logical checks. Below is a basic idea of using objects.

    function basicIdea(rules, obj) {
    
      const checksFns = {
        and: arr => arr.every(checkIt),
        or: arr => arr.some(checkIt),
      };
    
      const hasKey = key => key in obj;
    
      const checkIt = item => {
        if (typeof item === 'object') {
          const {
            op,
            checks
          } = item;
    
          return checksFns[op](checks);
        }
    
        return hasKey(item);
      }
    
      return checkIt(rules);
    }
    
    var obj1 = {
      a: 1,
      b: 1,
      c: 1
    };
    
    console.log('check and good', basicIdea({
      op: 'and',
      checks: ['a', 'b', 'c']
    }, obj1));
    
    console.log('check and bad', basicIdea({
      op: 'and',
      checks: ['a', 'b', 'd']
    }, obj1));
    
    console.log('check or good', basicIdea({
      op: 'or',
      checks: ['d', 'a']
    }, obj1));
    
    console.log('check or bad', basicIdea({
      op: 'or',
      checks: ['d', 'e']
    }, obj1));
    
    console.log('check and or good', basicIdea({
        op: 'and',
        checks: ['a', {
          op: 'or',
          checks: [
            'b',
            'c'
          ]
        }],
      },
      obj1));
      
      console.log('check and or bad', basicIdea({
        op: 'and',
        checks: ['a', {
          op: 'or',
          checks: [
            'd',
            'e'
          ]
        }],
      },
      obj1));
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search