Home > Net >  Check if number is in ranges described as string
Check if number is in ranges described as string

Time:01-11

I have ranges described as string let ranges = "0,71-140,34,142-216,20-30,7" (not soreted; one number eg 34 means range 34-34).

  • How to chceck that number num is in some range (of given ranges)
  • How to check that number is smaller than smallest range or bigger than biggest range?

This is inversion of this question.

const isInRanges = (ranges, num) => {
  return false; // magic here
}

const isOutOfRanges = (ranges, num) => {
  return false; // magic here
}


// ------------------------------------------------
// TESTS - whe should get allways TRUE in console
// ------------------------------------------------

let myRanges = "0,71-140,34,142-216,20-30,7";

// is in tests
let casesIn = [
  [0, true],
  [25, true],
  [35, false],
  [200, true],
  [8, false]
];

for (const c of casesIn) {
  console.log(c[0], isInRanges(myRanges, c[0]) == c[1])
}

// is out tests
let casesOut = [
  [-2, true],
  [60, false],
  [300, true],
  [7, false]
];

for (const c of casesOut) {
  console.log(c[0], isOutOfRanges(myRanges, c[0]) == c[1])
}

Solution will be two functions (look on snippet) which returns ture/false - and pass all test-cases (we shoud see allways 'true' on console).

CodePudding user response:

The code originally posted by @KamilKiełczewski can be trimmed down a bit, so that it looks like this.

const isInRanges = (ranges, num) => {
  return ranges.split(',')
    .map(r => r.split('-')) // we're splitting right away
    .some(r => r.length == 1 ? num ==  r[0] : num >=  r[0] && num <=  r[1]);
}

const isOutOfRanges = (ranges, num) => {
  // we're avoiding the sorting ...
  const sorted = ranges.match(/\d /g).map(Number);
  // ... because we're going to use min and max
  return num < Math.min(...sorted) || num > Math.max(...sorted);
}


// ------------------------------------------------
// TESTS - we should get allways TRUE in console
// ------------------------------------------------

let myRanges = "0,71-140,34,142-216,20-30,7";

// is in tests
let casesIn = [
  [0, true],
  [25, true],
  [35, false],
  [200, true],
  [8, false]
];

for (const c of casesIn) {
  console.log(c[0], isInRanges(myRanges, c[0]) == c[1])
}

// is out tests
let casesOut = [
  [-2, true],
  [60, false],
  [300, true],
  [7, false]
];

for (const c of casesOut) {
  console.log(c[0], isOutOfRanges(myRanges, c[0]) == c[1])
}

I was curious about performance, and whether this would have any problems scaling up, so I decided to run some tests on JSBench.me (original code vs this revision). After running a couple of consecutive tests, it seems that the trimmed down version is somewhat faster.

CodePudding user response:

Here is my answer (for future generations) - but may be someone have better?

const isInRanges = (ranges, num) => {
  return ranges.split(',')
    .map(r => r.split('-'))
    .some(r => r.length == 1 ? num ==  r[0] : num >=  r[0] && num <=  r[1]);
}

const isOutOfRanges = (ranges, num) => {
  const sorted = ranges.match(/\d /g).map(Number).sort((a, b) => a - b);
  return num < sorted.at(0) || num > sorted.at(-1);
}


// ------------------------------------------------
// TESTS - we should get allways TRUE in console
// ------------------------------------------------

let myRanges = "0,71-140,34,142-216,20-30,7";

// is in tests
let casesIn = [
  [0, true],
  [25, true],
  [35, false],
  [200, true],
  [8, false]
];

for (const c of casesIn) {
  console.log(c[0], isInRanges(myRanges, c[0]) == c[1])
}

// is out tests
let casesOut = [
  [-2, true],
  [60, false],
  [300, true],
  [7, false]
];

for (const c of casesOut) {
  console.log(c[0], isOutOfRanges(myRanges, c[0]) == c[1])
}

  • Related