1

There is a very common and easy task of looped iteration through some range in both directions:

var currentIndex = 0;
var range = ['a', 'b', 'c', 'd', 'e', 'f'];

function getNextItem(direction) {
    currentIndex += direction;
    if (currentIndex >= range.length) { currentIndex = 0; }
    if (currentIndex < 0) { currentIndex = range.length-1; }

    return range[currentIndex];
}        
// get next "right" item
console.log(getNextItem(1));

// get next "left" item
console.log(getNextItem(-1));

The code above works perfectly, but I spent about an hour trying to get rid of double if check.

Is there any way to solve if without if? Sort of one-liner maybe?

Denis O.
  • 1,841
  • 19
  • 37
  • 5
    Are you sure it works perfectly, `getNextItem(-1);` gives `undefined`? – Nick Parsons Sep 28 '19 at 01:26
  • You can also use ternary operator for that. – Saleh Mahmood Sep 28 '19 at 01:33
  • Btw, it should rather be an `if … else if` not a double `if` – Bergi Sep 28 '19 at 01:37
  • @Bergi should it? Why? – Denis O. Sep 28 '19 at 01:40
  • @DenisO. it will try to check both `if` condition on each iteration, whereas with `else .. if` it won't – Code Maniac Sep 28 '19 at 01:42
  • @DenisO. Because they are exclusive, you would either hit the end or the start of your array, but not both, and you would never want both statement to be executed. Of course, that can't happen given how the code is currently written, but using an `else` makes the intention clear, skips one unnecessary check, and makes mistakes cause less confusing results. – Bergi Sep 28 '19 at 01:44
  • Btw, also consider what your function should do when being called on an empty array. – Bergi Sep 28 '19 at 01:45
  • @Bergi, agree :) but this wasn't a production ready code, just an illustration of what i'm looking for. – Denis O. Sep 28 '19 at 01:48

1 Answers1

6

To turn the two ifs into one unconditional statement, you can add the range.length to the currentIndex and then use modulo:

var currentIndex = 0;
var range = ['a','b','c','d','e','f'];

function getNextItem(direction) {
    currentIndex = (currentIndex + direction + range.length) % range.length;
    return range[currentIndex];
}

// get next "right" item
console.log(getNextItem(1));
console.log(getNextItem(1));

// get next "left" item
console.log(getNextItem(-1));
console.log(getNextItem(-1));
console.log(getNextItem(-1));

console.log(getNextItem(4));
console.log(getNextItem(1));
console.log(getNextItem(1));
console.log(getNextItem(1));
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320