0

I have the following issue I have a set of JSON rules like so

{
    "event": {
        "type": "maxrulecount",
        "params": {
            "maxrulecount": 2
        }
    },
    "conditions": {
        "any": [
            {
                "all": [
                    {
                        "fact": "apples",
                        "value": "20",
                        "operator": "greaterThanInclusive"
                    }
                ]
            },
            {
                "all": [
                    {
                        "fact": "bananas",
                        "value": "100",
                        "operator": "greaterThanInclusive"
                    }
                ]
            }
        ]
    }
}


So i obviously convert this to an object but the number value remains a string so I have created a function that will convert any numbers that are strings into numbers like so

checkForNumberValues(rules) {
    // allows any number of numbers together or a decimal number
    let numberRegex = /^(([0-9]{1,})|([0-9]{1,}\.[0-9]{1,}))$/g;
    // yes a loop within a loop but time complexity is no issue here
    rules?.conditions?.any?.forEach((condition) => {
      condition?.all?.forEach((rule) => {
        console.log(rule.value, numberRegex.test(rule.value)); // this is working correctly
        if (numberRegex.test(rule.value)) {
          rule.value = Number(rule.value);
        }
      });
    });
    console.log(rules);
    return rules;
}

now i can see that it is correctly identifying numbers and setting the value but when i console the result like so

console.log(checkForNumberValues(rules));

I'ts returning the rules object with the string number values instead of the number values I set..

Do I need to do something special to set nested values??

Below is an example

let rules = {
  conditions: {
    any: [
      {
        all: [
          { fact: 'orange', value: '70' },
          { fact: 'apple', value: '10' },
          { fact: 'brocolli', value: '54' },
          { fact: 'kiwi fruit', value: '199' }
        ]
      }
    ]
  }
}

function checkForNumberValues(rules) {
  let numberRegex = /^(([0-9]{1,})|([0-9]{1,}\.[0-9]{1,}))$/g;
  rules.conditions.any.forEach((condition) => {
    condition.all.forEach((rule) => {
      if (numberRegex.test(rule.value)) {
         rule.value = Number(rule.value);
      }
    })
  });
  return rules;
}

console.log(checkForNumberValues(rules));

Any help would be appreciated!

Smokey Dawson
  • 8,827
  • 19
  • 77
  • 152

3 Answers3

1

Regexp "remembers" the last index where a match was found when the global flag g is used (-> Why does a RegExp with global flag give wrong results?)

Use parseInt()/Number() and then test for NaN

let rules = {
  conditions: {
    any: [
      {
        all: [
          { fact: 'orange', value: '70' },
          { fact: 'apple', value: '10' }
        ]
      }
    ]
  }
}

function checkForNumberValues(rules) {
  rules.conditions.any.forEach((condition) => {
    condition.all.forEach((rule) => {
      const val = parseInt(rule.value);
      
      if (!isNaN(val)) {
         rule.value = val;
      }
    })
  });
  return rules;
}

console.log(checkForNumberValues(rules));
Andreas
  • 21,535
  • 7
  • 47
  • 56
0

Use isNaN to check if the string is a number or not.

let rules = {
  conditions: {
    any: [
      {
        all: [
          { fact: 'orange', value: '70' },
          { fact: 'apple', value: '10' },
          { fact: 'brocolli', value: '54' },
          { fact: 'kiwi fruit', value: '199' }
        ]
      }
    ]
  }
}

function checkForNumberValues(rules) {
  rules.conditions.any.forEach((condition) => {
    condition.all.forEach((rule) => {
      if (!isNaN(rule.value)) {
         rule.value = Number(rule.value);
      }
    })
  });
  return rules;
}

console.log(checkForNumberValues(rules));
Akshay
  • 14,138
  • 5
  • 46
  • 70
0

you can try a different approach

let rules = {
        conditions: {
          any: [
            {
              all: [
                { fact: 'orange', value: '70' },
                { fact: 'apple', value: '10' }
              ]
            }
          ]
        }
      }
rules.conditions.any.filter(x=>{(x.all).forEach(x=>x.value=parseInt(x.value))})
console.log(rules)
Sven.hig
  • 4,449
  • 2
  • 8
  • 18