Skip to content

Validate Range of Numbers

I am trying to validate a comma separated list of numbers 1-384 unique (not repeating).

i.e.

  • 1, 2, 3, 5, 6, 7, 9 is valid
  • 1-3, 5-7, 9 is valid
  • 2, 2, 6 is invalid
  • 2, is invalid
  • 1, 2, 3, 4, 15, 6, 7, 385 is invalid because the last number is more than 384

I have tried the following RegEx pattern, but is not sufficient:

/^(?!.*(b(?:[1-9]|[1-2]d|3[0-1])b).*b1b)(?:[1-9]|[1-2]d|3[0-1])(?:,(?:[1-9]|[1-2]d|3[0-1]))*$/

Answer

You can try this-

function isValid(str) {
  let lower = 1, upper = 384;
  
  // Removing the unnecessary spaces
  str = str.replace(/s/g, '');
  
  // Split the string by comma (,)
  const nums = str.split(',');
  const track = {};
  
  // Visit the numbers
  for (const num of nums) {
    
    // Check if any number contains a dash (-)
    if (/-/.test(num)) {
      
      // If has dash then split by dash and get the upper and lower bounds.
      const [l, u] = num.split('-').map(x => x * 1);
      
      // Visit from lower to upper bound
      for (let i = l; i <= u; i++) {
        
        // If any number of the range doesn't exceed the upper
        // or lower bound i.e. [1, 384] range and did not
        // appear before then track this number.
        // otherwise return false i.e. mark it as invalid.
        if (i >= lower && i <= upper && track[i] === undefined) {
          track[i] = true;
        } else {
          return false;
        }
      }
      
    } else {
      
      // Checking again if it exceed the range [1, 384] or appears before.
      if (num * 1 >= lower && num * 1 <= upper && track[num] === undefined) {
        track[num] = true;
      } else {
        return false;
      }
    }
  }
  
  // If everything okay then return true, i.e. valid.
  return true;
}

const strs = [
  '1, 2, 3, 5, 6, 7, 9',
  '1-3, 5-7, 9',
  '2, 2, 6',
  '2,',
  '1, 2, 3, 4, 15, 6, 7, 385',
  '1-4, 3, 7-9, 10',
  '1-100, 102, 123',
  '1-100, 102, 99'
];

for (const str of strs) {
  console.log(str + ' => ' + (isValid(str) ? 'Valid': 'Invalid'));
}
.as-console-wrapper{min-height: 100%!important; top: 0}