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])
}