Home Communities
IT Knowledge
Inspiration
Languages
EN

# JavaScript - positive and negative around index wrapping / overlapping to address items in array

4 points
Created by:
413

In this article, we're going to have a look at how in JavaScript, properly address items by negative indexes or when we exceed indexes to overlap range to normal index.

Hint: you can read about experimental `Array` `at()` function here.

Quick solution:

``````// ONLINE-RUNNER:browser;

var array = ['first', 'middle', 'last'];

var index = -1;  // <------------------- change this index to your own, e.g. -2, -1, 0, 1, 2, 3, etc.
var value = array[(index % array.length + array.length) % array.length];

console.log(value);  // last``````

## Available solutions

### 1. Double modulo example

This section presents a solution that is based on the fact if we use two times modulo on indexes we are able to escape negative indexes too.

``````// ONLINE-RUNNER:browser;

function escapeIndex(index, count) {
return (index % count + count) % count;
}

// Usage example:

var arraySize = 10;

console.log(  escapeIndex(  0, arraySize ) );  // 0
console.log(  escapeIndex(  1, arraySize ) );  // 1
console.log(  escapeIndex(  2, arraySize ) );  // 2
console.log(  escapeIndex(  9, arraySize ) );  // 9

console.log( escapeIndex(  10, arraySize ) );  // 0
console.log( escapeIndex(  11, arraySize ) );  // 1
console.log( escapeIndex(  19, arraySize ) );  // 9
console.log( escapeIndex(  20, arraySize ) );  // 0
console.log( escapeIndex(  21, arraySize ) );  // 1

console.log( escapeIndex(  -1, arraySize ) );  // 9
console.log( escapeIndex(  -9, arraySize ) );  // 1
console.log( escapeIndex( -10, arraySize ) );  // 0
console.log( escapeIndex( -11, arraySize ) );  // 9
console.log( escapeIndex( -19, arraySize ) );  // 1
console.log( escapeIndex( -20, arraySize ) );  // 0
console.log( escapeIndex( -21, arraySize ) );  // 9

/*
----------------[ Calculations map ]--------------------

normal index       0   1   2   3   4   5   6   7   8   9

index exceeded    10  11  12  13  14  15  16  17  18  19
20  21  22  23  24  25  26  27  28  29
...

index negative   -10  -9  -8  -7  -6  -5  -4  -3  -2  -1
-20 -19 -18 -17 -16 -15 -14 -13 -12 -11
-30 -29 -28 -27 -26 -25 -24 -23 -22 -21
...

|   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |

result:            0   1   2   3   4   5   6   7   8   9

*/``````

### 2. Modulo with 2 cases example

This section shows a solution that uses `if` statement to split calculations for two cases: negative indexes and positive.

Used cases are based on:

1. modulo for positive indexes:
`itemIndex % arraySize`,
2. adding decreased with `1` maximal integer number in JavaScript and later use modulo for negative indexes:
`(itemIndex + 0x1FFFFFFFFFFFFE) % arraySize`.

Maximum integer number in JavaScript:

 Exponential Hexadecimal Decimal 2^53 - 1 0x1FFFFFFFFFFFFF 9007199254740991

Runnable examples are presented is below:

``````// ONLINE-RUNNER:browser;

function escapeIndex(itemIndex, arraySize) {
if (itemIndex < 0) {
return (itemIndex + 0x1FFFFFFFFFFFFE) % arraySize;
}
return itemIndex % arraySize;
}

// Usage example:

var arraySize = 10;

console.log(  escapeIndex(  0, arraySize ) );  // 0
console.log(  escapeIndex(  1, arraySize ) );  // 1
console.log(  escapeIndex(  2, arraySize ) );  // 2
console.log(  escapeIndex(  9, arraySize ) );  // 9

console.log( escapeIndex(  10, arraySize ) );  // 0
console.log( escapeIndex(  11, arraySize ) );  // 1
console.log( escapeIndex(  19, arraySize ) );  // 9
console.log( escapeIndex(  20, arraySize ) );  // 0
console.log( escapeIndex(  21, arraySize ) );  // 1

console.log( escapeIndex(  -1, arraySize ) );  // 9
console.log( escapeIndex(  -9, arraySize ) );  // 1
console.log( escapeIndex( -10, arraySize ) );  // 0
console.log( escapeIndex( -11, arraySize ) );  // 9
console.log( escapeIndex( -19, arraySize ) );  // 1
console.log( escapeIndex( -20, arraySize ) );  // 0
console.log( escapeIndex( -21, arraySize ) );  // 9``````

## 3. Wrapped array class example

In this section simple class for array wraping is presented.

``````// ONLINE-RUNNER:browser;

function escapeIndex(index, count) {
if(index < 0) {
return (index + 0x1FFFFFFFFFFFFE) % count;
}
return index % count;
}

function WrappedArray(array) {
this.getValue = function(index) {
var safeIndex = escapeIndex(index, array.length);
return array[safeIndex];
};
this.setValue = function(index, value) {
var safeIndex = escapeIndex(index, array.length);
array[safeIndex] = value;;
};
this.iterate = function(start, stop, callback) {
var safeStart = escapeIndex(start, array.length);
var safeStop = escapeIndex(stop, array.length);
if (safeStart < safeStop) {
for (var i = safeStart; i < safeStop; ++i) {
var result = callback(i, array[i]);
if (result !== undefined) {
array[i] = result;
}
}
} else {
for (var i = safeStart; i < array.length; ++i) {
var result = callback(i, array[i]);
if (result !== undefined) {
array[i] = result;
}
}
for (var i = 0; i < safeStop; ++i) {
var result = callback(i, array[i]);
if (result !== undefined) {
array[i] = result;
}
}
}
};
}

// Usage examples:

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var wrapper = new WrappedArray(array);

// Example 1

console.log( wrapper.getValue(  0 ) );  //  1
console.log( wrapper.getValue(  9 ) );  // 10
console.log( wrapper.getValue( -1 ) );  // 10
console.log( wrapper.getValue( 10 ) ); //  1

// Example 2

console.log( 'Iterating: <0, 9>' );
wrapper.iterate(0, 10, function(index, value) {
// 1 2 3 4 5 6 7 8 9 10
console.log( index + ': ' + value );
});

// Example 3

console.log( 'Iterating: <-1, 1>' );
wrapper.iterate(-1, 2, function(index, value) {
// 10 1 2
console.log( index + ': ' + value );
});

// Example 4

console.log( 'Iterating: <7, 6>' );
wrapper.iterate(7, 7, function(index, value) {
// 8 9 10 1 2 3 4 5 6 7
console.log( index + ': ' + value );
});

// Example 5

console.log( 'Iterating with zero setting: <-2, 1> = 8, 9, 0, 1' );
wrapper.iterate(-2, 2, function(index, value) {
return 0;  // by returning 0 we set items to 0 (setting 10 9 1 2 to 0)
});
wrapper.iterate(0, 10, function(index, value) {
// 0 0 3 4 5 6 7 8 0 0
console.log( index + ': ' + value );
});``````

## Alternative titles

Join to our subscribers to be up to date with content, news and offers.