Reputation: 11
I am trying to find the best way to generate an array that has the following output:
[135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 275, 276, 277 , 278, 279, 280, 281, 282, 283, 284, 285, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 675, 676, 677, 678, 679, 700, 701, 702, 703, 704, 705 ...
As you can see it has a set of limits from 140 - 280 - 420 - 560 - 700 ( adds 148 to each value) and then there's an interval with minus 5 and plus 5 for each value.
I already tried this approach
scrollFrom = Array.from(Array(bytesIndexTo).keys()).map(i => 140 + i * 140);
That returns me:
[140, 280, 420, 560, 700, ...
However I also need the plus and minus 5 values intervals...
I also noticed it uses to much resources.
const prev = [
[135,136,137,138,139],
[275,276,277,278,279],
];
const after = [
[141,142,143,144,145],
[281,282,283,284,285],
];
for (let i = 0; i < scrollFrom.length; i++) {
scrollFrom.push( scrollFrom[i] );
}
The purpose of this array is to have a set of values that will help me to identify a certain scroll position in order to execute a function, the addition of this intervals will help me to figure the scroll position even if the user scrolls fast.
Maybe I could load the values inside a .json and load them ?
What do you think ? thanks in advance
Upvotes: 0
Views: 276
Reputation: 707218
So, if you all you really want to do is to be able to test if a number is within 5 of a sentinel multiple, then I don't think you really want to be generating a giant array and using .includes()
. That would be slow. If you were going to pre-generate values, you should use a Set
and then use .has()
which should be a lot faster than .includes()
for a large set of data.
But, it seems to be that you can just calculate a lot faster without doing any pre-generation at all.
In the code below, we divide by the multiple (140) and then look at the remainder. If the remainder is <=5 or >= 135, then it's within 5 of the multiple, otherwise not. It's really that simple. Since it appears you don't want the numbers 0-5 (around the zero multiple) to be counted as true
, we add a special case for those.
// tests to see if a value is within 5 of a multiple of 140
const multiple = 140;
const over = 5;
const below = multiple - over;
function testValue(val) {
if (val < below) return false;
const delta = val % multiple; // divide by multiple, get remainder
return (delta <= over || delta >= below); // see if remainder in right range
}
// run some tests on numbers at edges of the interval ranges
[
0, 1,
134, 135, 140, 144, 145, 146, // around 140
274, 275, 280, 284, 285, 286, // around 280
414, 415, 420, 424, 425, 426, // around 420
554, 555, 560, 564, 565, 566 // around 560
].forEach(num => {
console.log(`${num}: ${testValue(num)}`);
});
Upvotes: 1
Reputation: 370679
Once you create an array of central values (eg [140, 280, 420, 560, 700]
), you can use flatMap
to iterate over each item and construct another array of the 5 values below and above it:
const bytesIndexTo = 4;
const result = Array.from(
{ length: bytesIndexTo },
(_, i) => (i + 1) * 140
)
.flatMap(num => Array.from(
{ length: 11 },
(_, j) => num - 5 + j
));
console.log(result);
Upvotes: 2