0

I have an array of values, specifically pixel offsets of a certain type of element.

Let's say they are in an array arrScroll[] with values [5, 10, 15, 50, 100, 250].

If my window scrolls past 5 pixels but not past 10 pixels, I get the index 0. If my window scrolls past 15 pixels but not past 50 pixels, I get the index 2. If it scrolls back below 10 pixels but not below 5, I get the index 0 again.

What I'm trying to do is find a graceful way (instead of a ton of conditionals for each possible range, as the number of ranges can change) to always get the lower of the two indexes of the scroll range that I am in, except at the range 0 to arrScroll[0], in which case I pass a different value than the index.

Another example: if I am in the range of arrScroll[3] and arrScroll[4] then I will obtain the index 3. Only once I pass the position of the higher index number do I get its index.

This has nothing to do with sorting as the values are already sorted from smallest to greatest. On a scroll event listener, I simply want to obtain the index of the lower of the two values comprising the index.

What would be the best way to organize this so that it can function for an array of arbitrary length?

More complete example:

I have the colors red, blue, and green. I have an array with values [100, 200, 300]. When my window scrolls past 100 pixels but not past 200 pixels, I will have something like $(element).css('background-color', colorArr[index]) where the color in colorArr[] at index 0 is red.

Then if the window scrolls past 200, but not past 300, I run the same code snippet, but the index is now 1 and the color is blue.

If I scroll back below 200 pixels but not below 100 pixels, the index is once again 0 and the color passed is red.

This is trivial to create with if statements if the length of the array is known, but I don't know how to do it for an array of arbitrary length.

AKor
  • 8,550
  • 27
  • 82
  • 136
  • Are you wanting the lower of the indexes, or the lower of the values at that index? – Taplar May 17 '18 at 15:33
  • 1
    Possible duplicate of [Sort by two values prioritizing on one of them](https://stackoverflow.com/questions/4576714/sort-by-two-values-prioritizing-on-one-of-them) – Zoe Edwards May 17 '18 at 15:33
  • @Taplar Shouldn't matter, so long as I have the lower index I can pull the value from the array. – AKor May 17 '18 at 15:34
  • @ThomasEdwards This isn't related to sorting as the values are already sorted. – AKor May 17 '18 at 15:35
  • 1
    This makes literally no sense as the array is already sorted, the smaller index always wins. – kemicofa ghost May 17 '18 at 15:39
  • @rottenoats This shouldn't have anything to do with sorting in the first place. On a scroll event listener, I am trying to have different behavior occur as the page scrolls in different pixel ranges. Such ranges are contained in the mentioned array. – AKor May 17 '18 at 15:40
  • I know this has nothing to do with sorting, however you mention that the array is already sorted, so what's the problem? You have two indexes 3 and 4 and you want the lowest value of the two... it'll be the lower index all the time since it's already sorted. – kemicofa ghost May 17 '18 at 15:42
  • @rottenoats Yes, that's the idea. But if I don't know how long the length of the array is, I can't create dozens of if statements and hope it works. I was wondering if there was a more graceful way. I've made a more complete example in the original post to showcase my exact use for this. – AKor May 17 '18 at 15:46
  • Akor check my answer, played around with some values and should work now. – kemicofa ghost May 17 '18 at 15:58

2 Answers2

1

If I'm not mistaken you're seeking to find index based on a value?

let arr = [5, 10, 15, 50, 100, 250];
let colorArr = ["red", "blue", "green", "yellow", "orange", "black"]
//fake listener
let scrollListener = (pixelScrolled) => {
   let index = (arr.findIndex((element)=>pixelScrolled<element)+arr.length)%(arr.length+1);
   $(document.body).css('background-color', colorArr[index])
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="(()=>scrollListener(9))()">fake scroll toggle : 9</button>
<button onclick="(()=>scrollListener(49))()">fake scroll toggle : 49</button>
<button onclick="(()=>scrollListener(250))()">fake scroll toggle :  250</button>
kemicofa ghost
  • 16,349
  • 8
  • 82
  • 131
0

I'd iterate on your arrScroll values starting from the begining, assuming your offsets are always sorted in a growing order and break as soon as your test position is greater than the tested index

var test = function (position, offsets) {
    for (var index = 0; index < offsets.length - 1; index++) {
      if (position < offsets[index]) break;
    }
    
    return index > 0 ? index - 1 : 'something';
}

// will return index 1 cuz 4 is bw 1 and 5
console.log(test(4, [0, 1, 5, 10, 20, 42]))

// will return 3
console.log(test(12, [0, 1, 5, 10, 20, 42]))

// would return 0, but would return "something" since this is your special case
console.log(test(16, [20, 100]))

That way you iterate only on part of your offset arrays, exiting as soon as possible

guillaumepotier
  • 7,369
  • 8
  • 45
  • 72