0

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

4
  • Why do you have to generate the entire array if you're just trying to compare scroll positions? Wouldn't it be better to just see if it's within 5 of one of your sentinel positions? I don't understand why you have to pre-build all the possible values? Why not just calculate on the fly?
    – jfriend00
    Commented Mar 22, 2020 at 1:27
  • It uses the include function to check if the value is inside the array, and the array is quite big therefore a simple check won't work Commented Mar 22, 2020 at 2:07
  • I posted an answer that solves that problem a different way by just doing a quick calculation to see if a given number if within 5 of a multiple of 140. No pregenerated array needed.
    – jfriend00
    Commented Mar 22, 2020 at 2:34
  • FYI, these numbers in the array in your question 675, 676, 677, 678, 679 should be 695, 696, 697, 698, 699.
    – jfriend00
    Commented Mar 22, 2020 at 2:56

2 Answers 2

2

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);

1

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)}`);
});

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.